Initial commit
This commit is contained in:
81
prisma/migrations/202604070001_init/migration.sql
Normal file
81
prisma/migrations/202604070001_init/migration.sql
Normal file
@@ -0,0 +1,81 @@
|
||||
CREATE TYPE "Role" AS ENUM ('ADMIN', 'FINANCE', 'MEMBER');
|
||||
CREATE TYPE "ApprovalType" AS ENUM ('CHAIR_A', 'CHAIR_B', 'FINANCE');
|
||||
CREATE TYPE "ApprovalStatus" AS ENUM ('PENDING', 'APPROVED');
|
||||
|
||||
CREATE TABLE "working_groups" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"total_budget" DECIMAL(10,2) NOT NULL,
|
||||
"color_code" TEXT NOT NULL,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL,
|
||||
CONSTRAINT "working_groups_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "users" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"email" TEXT NOT NULL,
|
||||
"password_hash" TEXT NOT NULL,
|
||||
"role" "Role" NOT NULL,
|
||||
"approval_preference" "ApprovalType",
|
||||
"working_group_id" TEXT,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL,
|
||||
CONSTRAINT "users_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "expenses" (
|
||||
"id" TEXT NOT NULL,
|
||||
"title" TEXT NOT NULL,
|
||||
"amount" DECIMAL(10,2) NOT NULL,
|
||||
"creator_id" TEXT NOT NULL,
|
||||
"ag_id" TEXT NOT NULL,
|
||||
"approval_status" "ApprovalStatus" NOT NULL DEFAULT 'PENDING',
|
||||
"paid_at" TIMESTAMP(3),
|
||||
"documented_at" TIMESTAMP(3),
|
||||
"proof_url" TEXT,
|
||||
"notes" TEXT,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL,
|
||||
CONSTRAINT "expenses_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "approvals" (
|
||||
"id" TEXT NOT NULL,
|
||||
"expense_id" TEXT NOT NULL,
|
||||
"user_id" TEXT NOT NULL,
|
||||
"approval_type" "ApprovalType" NOT NULL,
|
||||
"timestamp" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT "approvals_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX "working_groups_name_key" ON "working_groups"("name");
|
||||
CREATE UNIQUE INDEX "users_email_key" ON "users"("email");
|
||||
CREATE UNIQUE INDEX "approvals_expense_id_approval_type_key" ON "approvals"("expense_id", "approval_type");
|
||||
|
||||
ALTER TABLE "users"
|
||||
ADD CONSTRAINT "users_working_group_id_fkey"
|
||||
FOREIGN KEY ("working_group_id") REFERENCES "working_groups"("id")
|
||||
ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "expenses"
|
||||
ADD CONSTRAINT "expenses_creator_id_fkey"
|
||||
FOREIGN KEY ("creator_id") REFERENCES "users"("id")
|
||||
ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "expenses"
|
||||
ADD CONSTRAINT "expenses_ag_id_fkey"
|
||||
FOREIGN KEY ("ag_id") REFERENCES "working_groups"("id")
|
||||
ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "approvals"
|
||||
ADD CONSTRAINT "approvals_expense_id_fkey"
|
||||
FOREIGN KEY ("expense_id") REFERENCES "expenses"("id")
|
||||
ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "approvals"
|
||||
ADD CONSTRAINT "approvals_user_id_fkey"
|
||||
FOREIGN KEY ("user_id") REFERENCES "users"("id")
|
||||
ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
84
prisma/migrations/202604071700_budget_accounts/migration.sql
Normal file
84
prisma/migrations/202604071700_budget_accounts/migration.sql
Normal file
@@ -0,0 +1,84 @@
|
||||
ALTER TABLE "users" ADD COLUMN "username" TEXT;
|
||||
|
||||
WITH ranked AS (
|
||||
SELECT
|
||||
id,
|
||||
CASE
|
||||
WHEN lower(regexp_replace(split_part(email, '@', 1), '[^a-zA-Z0-9_-]', '-', 'g')) = ''
|
||||
THEN CONCAT('user-', substring(id from 1 for 6))
|
||||
ELSE lower(regexp_replace(split_part(email, '@', 1), '[^a-zA-Z0-9_-]', '-', 'g'))
|
||||
END AS base,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY CASE
|
||||
WHEN lower(regexp_replace(split_part(email, '@', 1), '[^a-zA-Z0-9_-]', '-', 'g')) = ''
|
||||
THEN CONCAT('user-', substring(id from 1 for 6))
|
||||
ELSE lower(regexp_replace(split_part(email, '@', 1), '[^a-zA-Z0-9_-]', '-', 'g'))
|
||||
END
|
||||
ORDER BY created_at, id
|
||||
) AS rn
|
||||
FROM "users"
|
||||
)
|
||||
UPDATE "users" AS u
|
||||
SET "username" = CASE
|
||||
WHEN ranked.rn = 1 THEN ranked.base
|
||||
ELSE CONCAT(ranked.base, '-', ranked.rn)
|
||||
END
|
||||
FROM ranked
|
||||
WHERE u.id = ranked.id;
|
||||
|
||||
ALTER TABLE "users" ALTER COLUMN "username" SET NOT NULL;
|
||||
ALTER TABLE "users" ALTER COLUMN "email" DROP NOT NULL;
|
||||
CREATE UNIQUE INDEX "users_username_key" ON "users"("username");
|
||||
|
||||
CREATE TABLE "budgets" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"total_budget" DECIMAL(10,2) NOT NULL,
|
||||
"color_code" TEXT NOT NULL,
|
||||
"working_group_id" TEXT NOT NULL,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL,
|
||||
CONSTRAINT "budgets_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
INSERT INTO "budgets" (
|
||||
"id",
|
||||
"name",
|
||||
"total_budget",
|
||||
"color_code",
|
||||
"working_group_id",
|
||||
"created_at",
|
||||
"updated_at"
|
||||
)
|
||||
SELECT
|
||||
CONCAT('budget_', "id"),
|
||||
'Hauptbudget',
|
||||
"total_budget",
|
||||
"color_code",
|
||||
"id",
|
||||
"created_at",
|
||||
"updated_at"
|
||||
FROM "working_groups";
|
||||
|
||||
CREATE UNIQUE INDEX "budgets_working_group_id_name_key" ON "budgets"("working_group_id", "name");
|
||||
|
||||
ALTER TABLE "budgets"
|
||||
ADD CONSTRAINT "budgets_working_group_id_fkey"
|
||||
FOREIGN KEY ("working_group_id") REFERENCES "working_groups"("id")
|
||||
ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "expenses" RENAME COLUMN "notes" TO "description";
|
||||
ALTER TABLE "expenses" ADD COLUMN "budget_id" TEXT;
|
||||
|
||||
UPDATE "expenses"
|
||||
SET "budget_id" = CONCAT('budget_', "ag_id");
|
||||
|
||||
ALTER TABLE "expenses" ALTER COLUMN "budget_id" SET NOT NULL;
|
||||
|
||||
ALTER TABLE "expenses"
|
||||
ADD CONSTRAINT "expenses_budget_id_fkey"
|
||||
FOREIGN KEY ("budget_id") REFERENCES "budgets"("id")
|
||||
ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "working_groups" DROP COLUMN "total_budget";
|
||||
ALTER TABLE "working_groups" DROP COLUMN "color_code";
|
||||
@@ -0,0 +1,60 @@
|
||||
CREATE TYPE "ExpenseRecurrence" AS ENUM ('NONE', 'MONTHLY');
|
||||
|
||||
CREATE TABLE "accounting_periods" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"starts_at" TIMESTAMP(3) NOT NULL,
|
||||
"ends_at" TIMESTAMP(3) NOT NULL,
|
||||
"is_current" BOOLEAN NOT NULL DEFAULT false,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL,
|
||||
CONSTRAINT "accounting_periods_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX "accounting_periods_name_key" ON "accounting_periods"("name");
|
||||
CREATE UNIQUE INDEX "accounting_periods_is_current_key" ON "accounting_periods"("is_current") WHERE "is_current" = true;
|
||||
|
||||
INSERT INTO "accounting_periods" (
|
||||
"id",
|
||||
"name",
|
||||
"starts_at",
|
||||
"ends_at",
|
||||
"is_current",
|
||||
"created_at",
|
||||
"updated_at"
|
||||
)
|
||||
VALUES (
|
||||
'period_current',
|
||||
CONCAT('Haushalt ', EXTRACT(YEAR FROM CURRENT_DATE)::text),
|
||||
date_trunc('year', CURRENT_DATE)::timestamp(3),
|
||||
(date_trunc('year', CURRENT_DATE) + interval '1 year' - interval '1 day')::timestamp(3),
|
||||
true,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
ALTER TABLE "budgets" ADD COLUMN "period_id" TEXT;
|
||||
ALTER TABLE "expenses" ADD COLUMN "period_id" TEXT;
|
||||
ALTER TABLE "expenses" ADD COLUMN "recurrence" "ExpenseRecurrence" NOT NULL DEFAULT 'NONE';
|
||||
|
||||
UPDATE "budgets"
|
||||
SET "period_id" = 'period_current';
|
||||
|
||||
UPDATE "expenses"
|
||||
SET "period_id" = 'period_current';
|
||||
|
||||
ALTER TABLE "budgets" ALTER COLUMN "period_id" SET NOT NULL;
|
||||
ALTER TABLE "expenses" ALTER COLUMN "period_id" SET NOT NULL;
|
||||
|
||||
DROP INDEX "budgets_working_group_id_name_key";
|
||||
CREATE UNIQUE INDEX "budgets_working_group_id_period_id_name_key" ON "budgets"("working_group_id", "period_id", "name");
|
||||
|
||||
ALTER TABLE "budgets"
|
||||
ADD CONSTRAINT "budgets_period_id_fkey"
|
||||
FOREIGN KEY ("period_id") REFERENCES "accounting_periods"("id")
|
||||
ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "expenses"
|
||||
ADD CONSTRAINT "expenses_period_id_fkey"
|
||||
FOREIGN KEY ("period_id") REFERENCES "accounting_periods"("id")
|
||||
ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
20
prisma/migrations/202604081930_audit_logs/migration.sql
Normal file
20
prisma/migrations/202604081930_audit_logs/migration.sql
Normal file
@@ -0,0 +1,20 @@
|
||||
CREATE TABLE "audit_logs" (
|
||||
"id" TEXT NOT NULL,
|
||||
"actor_id" TEXT,
|
||||
"action" TEXT NOT NULL,
|
||||
"entity_type" TEXT NOT NULL,
|
||||
"entity_id" TEXT,
|
||||
"entity_label" TEXT,
|
||||
"summary" TEXT NOT NULL,
|
||||
"metadata" JSONB,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "audit_logs_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE INDEX "audit_logs_created_at_idx" ON "audit_logs"("created_at");
|
||||
|
||||
ALTER TABLE "audit_logs"
|
||||
ADD CONSTRAINT "audit_logs_actor_id_fkey"
|
||||
FOREIGN KEY ("actor_id") REFERENCES "users"("id")
|
||||
ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
146
prisma/schema.prisma
Normal file
146
prisma/schema.prisma
Normal file
@@ -0,0 +1,146 @@
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
enum Role {
|
||||
ADMIN
|
||||
FINANCE
|
||||
MEMBER
|
||||
}
|
||||
|
||||
enum ApprovalType {
|
||||
CHAIR_A
|
||||
CHAIR_B
|
||||
FINANCE
|
||||
}
|
||||
|
||||
enum ApprovalStatus {
|
||||
PENDING
|
||||
APPROVED
|
||||
}
|
||||
|
||||
enum ExpenseRecurrence {
|
||||
NONE
|
||||
MONTHLY
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
username String @unique
|
||||
email String? @unique
|
||||
passwordHash String @map("password_hash")
|
||||
role Role
|
||||
approvalPreference ApprovalType? @map("approval_preference")
|
||||
workingGroupId String? @map("working_group_id")
|
||||
workingGroup WorkingGroup? @relation(fields: [workingGroupId], references: [id], onDelete: SetNull)
|
||||
createdExpenses Expense[] @relation("ExpenseCreator")
|
||||
approvals Approval[]
|
||||
auditLogs AuditLog[]
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
@@map("users")
|
||||
}
|
||||
|
||||
model AccountingPeriod {
|
||||
id String @id @default(cuid())
|
||||
name String @unique
|
||||
startsAt DateTime @map("starts_at")
|
||||
endsAt DateTime @map("ends_at")
|
||||
isCurrent Boolean @default(false) @map("is_current")
|
||||
budgets Budget[]
|
||||
expenses Expense[]
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
@@map("accounting_periods")
|
||||
}
|
||||
|
||||
model WorkingGroup {
|
||||
id String @id @default(cuid())
|
||||
name String @unique
|
||||
members User[]
|
||||
budgets Budget[]
|
||||
expenses Expense[]
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
@@map("working_groups")
|
||||
}
|
||||
|
||||
model Budget {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
totalBudget Decimal @db.Decimal(10, 2) @map("total_budget")
|
||||
colorCode String @map("color_code")
|
||||
workingGroupId String @map("working_group_id")
|
||||
periodId String @map("period_id")
|
||||
workingGroup WorkingGroup @relation(fields: [workingGroupId], references: [id], onDelete: Cascade)
|
||||
period AccountingPeriod @relation(fields: [periodId], references: [id], onDelete: Restrict)
|
||||
expenses Expense[]
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
@@unique([workingGroupId, periodId, name])
|
||||
@@map("budgets")
|
||||
}
|
||||
|
||||
model Expense {
|
||||
id String @id @default(cuid())
|
||||
title String
|
||||
description String?
|
||||
amount Decimal @db.Decimal(10, 2)
|
||||
creatorId String @map("creator_id")
|
||||
agId String @map("ag_id")
|
||||
budgetId String @map("budget_id")
|
||||
periodId String @map("period_id")
|
||||
approvalStatus ApprovalStatus @default(PENDING) @map("approval_status")
|
||||
recurrence ExpenseRecurrence @default(NONE)
|
||||
paidAt DateTime? @map("paid_at")
|
||||
documentedAt DateTime? @map("documented_at")
|
||||
proofUrl String? @map("proof_url")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
creator User @relation("ExpenseCreator", fields: [creatorId], references: [id], onDelete: Restrict)
|
||||
workingGroup WorkingGroup @relation(fields: [agId], references: [id], onDelete: Cascade)
|
||||
budget Budget @relation(fields: [budgetId], references: [id], onDelete: Restrict)
|
||||
period AccountingPeriod @relation(fields: [periodId], references: [id], onDelete: Restrict)
|
||||
approvals Approval[]
|
||||
|
||||
@@map("expenses")
|
||||
}
|
||||
|
||||
model Approval {
|
||||
id String @id @default(cuid())
|
||||
expenseId String @map("expense_id")
|
||||
userId String @map("user_id")
|
||||
approvalType ApprovalType @map("approval_type")
|
||||
timestamp DateTime @default(now())
|
||||
expense Expense @relation(fields: [expenseId], references: [id], onDelete: Cascade)
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([expenseId, approvalType])
|
||||
@@map("approvals")
|
||||
}
|
||||
|
||||
model AuditLog {
|
||||
id String @id @default(cuid())
|
||||
actorId String? @map("actor_id")
|
||||
actor User? @relation(fields: [actorId], references: [id], onDelete: SetNull)
|
||||
action String
|
||||
entityType String @map("entity_type")
|
||||
entityId String? @map("entity_id")
|
||||
entityLabel String? @map("entity_label")
|
||||
summary String
|
||||
metadata Json?
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
@@index([createdAt])
|
||||
@@map("audit_logs")
|
||||
}
|
||||
250
prisma/seed.ts
Normal file
250
prisma/seed.ts
Normal file
@@ -0,0 +1,250 @@
|
||||
import { ApprovalStatus, ApprovalType, ExpenseRecurrence, PrismaClient, Role } from "@prisma/client";
|
||||
import bcrypt from "bcryptjs";
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
async function upsertCurrentPeriod() {
|
||||
const year = new Date().getFullYear();
|
||||
const startsAt = new Date(Date.UTC(year, 0, 1));
|
||||
const endsAt = new Date(Date.UTC(year, 11, 31, 23, 59, 59));
|
||||
|
||||
await prisma.accountingPeriod.updateMany({
|
||||
data: {
|
||||
isCurrent: false
|
||||
}
|
||||
});
|
||||
|
||||
return prisma.accountingPeriod.upsert({
|
||||
where: {
|
||||
name: `Haushalt ${year}`
|
||||
},
|
||||
update: {
|
||||
startsAt,
|
||||
endsAt,
|
||||
isCurrent: true
|
||||
},
|
||||
create: {
|
||||
name: `Haushalt ${year}`,
|
||||
startsAt,
|
||||
endsAt,
|
||||
isCurrent: true
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function upsertWorkingGroup(name: string) {
|
||||
return prisma.workingGroup.upsert({
|
||||
where: { name },
|
||||
update: {},
|
||||
create: {
|
||||
name
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function upsertBudget(
|
||||
workingGroupId: string,
|
||||
periodId: string,
|
||||
name: string,
|
||||
totalBudget: number,
|
||||
colorCode: string
|
||||
) {
|
||||
return prisma.budget.upsert({
|
||||
where: {
|
||||
workingGroupId_periodId_name: {
|
||||
workingGroupId,
|
||||
periodId,
|
||||
name
|
||||
}
|
||||
},
|
||||
update: {
|
||||
totalBudget,
|
||||
colorCode
|
||||
},
|
||||
create: {
|
||||
name,
|
||||
totalBudget,
|
||||
colorCode,
|
||||
workingGroupId,
|
||||
periodId
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const passwordHash = await bcrypt.hash("demo123!", 12);
|
||||
const currentPeriod = await upsertCurrentPeriod();
|
||||
|
||||
const deko = await upsertWorkingGroup("AG Deko");
|
||||
const awareness = await upsertWorkingGroup("AG Awareness");
|
||||
const technik = await upsertWorkingGroup("AG Technik");
|
||||
|
||||
await upsertBudget(deko.id, currentPeriod.id, "Deko Hauptbudget", 0, "#FFB94A");
|
||||
await upsertBudget(awareness.id, currentPeriod.id, "Awareness Hauptbudget", 800, "#68A35D");
|
||||
const technikBudget = await upsertBudget(technik.id, currentPeriod.id, "Technik Infrastruktur", 1500, "#5677F6");
|
||||
|
||||
await prisma.user.upsert({
|
||||
where: { username: "vorstand-a" },
|
||||
update: {
|
||||
name: "Admin 1",
|
||||
username: "vorstand-a",
|
||||
email: null,
|
||||
passwordHash,
|
||||
role: Role.ADMIN,
|
||||
approvalPreference: ApprovalType.CHAIR_A,
|
||||
workingGroupId: null
|
||||
},
|
||||
create: {
|
||||
name: "Admin 1",
|
||||
username: "vorstand-a",
|
||||
email: null,
|
||||
passwordHash,
|
||||
role: Role.ADMIN,
|
||||
approvalPreference: ApprovalType.CHAIR_A
|
||||
}
|
||||
});
|
||||
|
||||
await prisma.user.upsert({
|
||||
where: { username: "vorstand-b" },
|
||||
update: {
|
||||
name: "Admin 2",
|
||||
username: "vorstand-b",
|
||||
email: null,
|
||||
passwordHash,
|
||||
role: Role.ADMIN,
|
||||
approvalPreference: ApprovalType.CHAIR_B,
|
||||
workingGroupId: null
|
||||
},
|
||||
create: {
|
||||
name: "Admin 2",
|
||||
username: "vorstand-b",
|
||||
email: null,
|
||||
passwordHash,
|
||||
role: Role.ADMIN,
|
||||
approvalPreference: ApprovalType.CHAIR_B
|
||||
}
|
||||
});
|
||||
|
||||
await prisma.user.upsert({
|
||||
where: { username: "finanzen" },
|
||||
update: {
|
||||
name: "Finanz-AG",
|
||||
username: "finanzen",
|
||||
email: null,
|
||||
passwordHash,
|
||||
role: Role.FINANCE,
|
||||
approvalPreference: ApprovalType.FINANCE,
|
||||
workingGroupId: null
|
||||
},
|
||||
create: {
|
||||
name: "Finanz-AG",
|
||||
username: "finanzen",
|
||||
email: null,
|
||||
passwordHash,
|
||||
role: Role.FINANCE,
|
||||
approvalPreference: ApprovalType.FINANCE
|
||||
}
|
||||
});
|
||||
|
||||
await prisma.user.upsert({
|
||||
where: { username: "deko" },
|
||||
update: {
|
||||
name: "Deko Mitglied",
|
||||
username: "deko",
|
||||
email: null,
|
||||
passwordHash,
|
||||
role: Role.MEMBER,
|
||||
approvalPreference: null,
|
||||
workingGroupId: deko.id
|
||||
},
|
||||
create: {
|
||||
name: "Deko Mitglied",
|
||||
username: "deko",
|
||||
email: null,
|
||||
passwordHash,
|
||||
role: Role.MEMBER,
|
||||
workingGroupId: deko.id
|
||||
}
|
||||
});
|
||||
|
||||
await prisma.user.upsert({
|
||||
where: { username: "technik" },
|
||||
update: {
|
||||
name: "Technik Mitglied",
|
||||
username: "technik",
|
||||
email: null,
|
||||
passwordHash,
|
||||
role: Role.MEMBER,
|
||||
approvalPreference: null,
|
||||
workingGroupId: technik.id
|
||||
},
|
||||
create: {
|
||||
name: "Technik Mitglied",
|
||||
username: "technik",
|
||||
email: null,
|
||||
passwordHash,
|
||||
role: Role.MEMBER,
|
||||
workingGroupId: technik.id
|
||||
}
|
||||
});
|
||||
|
||||
const existingExpense = await prisma.expense.findFirst({
|
||||
where: { title: "Muster: Kabelbinder" }
|
||||
});
|
||||
|
||||
if (!existingExpense) {
|
||||
const technikUser = await prisma.user.findUniqueOrThrow({
|
||||
where: { username: "technik" }
|
||||
});
|
||||
|
||||
await prisma.expense.create({
|
||||
data: {
|
||||
title: "Muster: Kabelbinder",
|
||||
description: "Beispiel fuer einen automatisch freigegebenen Infrastrukturposten.",
|
||||
amount: 24.5,
|
||||
creatorId: technikUser.id,
|
||||
agId: technik.id,
|
||||
budgetId: technikBudget.id,
|
||||
periodId: currentPeriod.id,
|
||||
approvalStatus: ApprovalStatus.APPROVED,
|
||||
proofUrl: null,
|
||||
recurrence: ExpenseRecurrence.NONE
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const existingSubscription = await prisma.expense.findFirst({
|
||||
where: { title: "Muster: Vereinssoftware Abo" }
|
||||
});
|
||||
|
||||
if (!existingSubscription) {
|
||||
const financeUser = await prisma.user.findUniqueOrThrow({
|
||||
where: { username: "finanzen" }
|
||||
});
|
||||
|
||||
await prisma.expense.create({
|
||||
data: {
|
||||
title: "Muster: Vereinssoftware Abo",
|
||||
description: "Monatlich wiederkehrendes Beispielabo fuer die Uebersicht.",
|
||||
amount: 19,
|
||||
creatorId: financeUser.id,
|
||||
agId: technik.id,
|
||||
budgetId: technikBudget.id,
|
||||
periodId: currentPeriod.id,
|
||||
approvalStatus: ApprovalStatus.APPROVED,
|
||||
proofUrl: null,
|
||||
recurrence: ExpenseRecurrence.MONTHLY
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
.then(async () => {
|
||||
await prisma.$disconnect();
|
||||
})
|
||||
.catch(async (error) => {
|
||||
console.error(error);
|
||||
await prisma.$disconnect();
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user