All checks were successful
CI / build-and-deploy (push) Successful in 1m22s
Den Zeitraum-Bereich habe ich dabei gleich mit aufgeräumt: die Auswahl des aktuellen Haushalts ist breiter und sauberer angeordnet, und die Desktop-Nutzerverwaltung ist jetzt wirklich links Anlegen + Schwelle und rechts die Nutzerliste. Seed und Backup/Restore kennen die neuen Felder ebenfalls in seed.ts, route.ts und route.ts.
231 lines
5.4 KiB
TypeScript
231 lines
5.4 KiB
TypeScript
import { ApprovalStatus, ApprovalType, ExpenseRecurrence, PrismaClient, Role } from "@prisma/client";
|
|
import bcrypt from "bcryptjs";
|
|
|
|
const prisma = new PrismaClient();
|
|
|
|
const APPROVAL_THRESHOLD = 50;
|
|
|
|
async function upsertAppSettings() {
|
|
await prisma.appSettings.upsert({
|
|
where: { id: "global" },
|
|
update: {
|
|
approvalThreshold: APPROVAL_THRESHOLD
|
|
},
|
|
create: {
|
|
id: "global",
|
|
approvalThreshold: APPROVAL_THRESHOLD
|
|
}
|
|
});
|
|
}
|
|
|
|
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 upsertUser(input: {
|
|
username: string;
|
|
role: Role;
|
|
passwordHash: string;
|
|
workingGroupId?: string | null;
|
|
approvalPermissions: ApprovalType[];
|
|
}) {
|
|
const approvalPreference = input.approvalPermissions[0] ?? null;
|
|
|
|
await prisma.user.upsert({
|
|
where: { username: input.username },
|
|
update: {
|
|
name: input.username,
|
|
username: input.username,
|
|
email: null,
|
|
passwordHash: input.passwordHash,
|
|
role: input.role,
|
|
approvalPreference,
|
|
approvalPermissions: input.approvalPermissions,
|
|
workingGroupId: input.workingGroupId ?? null
|
|
},
|
|
create: {
|
|
name: input.username,
|
|
username: input.username,
|
|
email: null,
|
|
passwordHash: input.passwordHash,
|
|
role: input.role,
|
|
approvalPreference,
|
|
approvalPermissions: input.approvalPermissions,
|
|
workingGroupId: input.workingGroupId ?? null
|
|
}
|
|
});
|
|
}
|
|
|
|
async function main() {
|
|
const passwordHash = await bcrypt.hash("demo123!", 12);
|
|
|
|
await upsertAppSettings();
|
|
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 upsertUser({
|
|
username: "vorstand-a",
|
|
role: Role.ADMIN,
|
|
passwordHash,
|
|
approvalPermissions: [ApprovalType.CHAIR_A]
|
|
});
|
|
|
|
await upsertUser({
|
|
username: "vorstand-b",
|
|
role: Role.ADMIN,
|
|
passwordHash,
|
|
approvalPermissions: [ApprovalType.CHAIR_B]
|
|
});
|
|
|
|
await upsertUser({
|
|
username: "finanzen",
|
|
role: Role.FINANCE,
|
|
passwordHash,
|
|
approvalPermissions: [ApprovalType.FINANCE]
|
|
});
|
|
|
|
await upsertUser({
|
|
username: "deko",
|
|
role: Role.MEMBER,
|
|
passwordHash,
|
|
workingGroupId: deko.id,
|
|
approvalPermissions: []
|
|
});
|
|
|
|
await upsertUser({
|
|
username: "technik",
|
|
role: Role.MEMBER,
|
|
passwordHash,
|
|
workingGroupId: technik.id,
|
|
approvalPermissions: []
|
|
});
|
|
|
|
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);
|
|
}); |