mirror of
https://github.com/Since-3/Kuma.git
synced 2026-10-12 20:51:18 +00:00
added chaching and serialisation and indexing
This commit is contained in:
parent
e05984c1c3
commit
06d1290921
6 changed files with 177 additions and 252 deletions
|
|
@ -60,6 +60,8 @@ model Employee {
|
|||
trainings UserTraining[]
|
||||
createdAt DateTime? @default(now())
|
||||
updatedAt DateTime? @updatedAt
|
||||
|
||||
@@index([createdBy])
|
||||
}
|
||||
|
||||
model UserTraining {
|
||||
|
|
@ -98,6 +100,8 @@ model Business {
|
|||
manager Manager @relation(fields: [managerId], references: [id])
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([managerId])
|
||||
}
|
||||
|
||||
model Course {
|
||||
|
|
@ -121,6 +125,10 @@ model Course {
|
|||
bookings CourseBooking[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([createdBy])
|
||||
@@index([date])
|
||||
@@index([status])
|
||||
}
|
||||
|
||||
model Room {
|
||||
|
|
@ -129,6 +137,8 @@ model Room {
|
|||
createdBy String // Manager ID who created the room
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([createdBy])
|
||||
}
|
||||
|
||||
model CourseBooking {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { createClient } from "@/src/lib/supabase/server";
|
||||
import { prisma } from "@/src/lib/prisma";
|
||||
import { cache } from "react";
|
||||
import { unstable_cache } from "next/cache";
|
||||
|
||||
// Define the user data types
|
||||
export type UserData = {
|
||||
|
|
@ -43,6 +44,7 @@ export type EmployeeData = {
|
|||
qualification: string | null;
|
||||
pbSrc: string | null;
|
||||
createdAt: Date | null;
|
||||
createdBy: string | null;
|
||||
role: "employee";
|
||||
permissions: {
|
||||
employees: { view: boolean; create: boolean; edit: boolean; delete: boolean };
|
||||
|
|
@ -53,192 +55,159 @@ export type EmployeeData = {
|
|||
|
||||
export type AuthUserData = UserData | ManagerData | EmployeeData;
|
||||
|
||||
// Note: We don't use in-memory caching because this app runs on Vercel (serverless)
|
||||
// Serverless functions are stateless - in-memory cache would be:
|
||||
// 1. Inconsistent across Lambda instances
|
||||
// 2. Lost on cold starts
|
||||
// 3. Not shared between requests
|
||||
// Instead, we rely on React's cache() for per-request deduplication only.
|
||||
|
||||
let userDataCallCount = 0;
|
||||
let supabaseCallCount = 0;
|
||||
|
||||
// Get authenticated user from Supabase
|
||||
// Uses React's cache() for per-request deduplication
|
||||
// No cross-request caching due to serverless architecture
|
||||
export const getUser = cache(async () => {
|
||||
supabaseCallCount++;
|
||||
console.log(`🔐 [AUTH] getUser called (count: ${supabaseCallCount})`);
|
||||
|
||||
const supabase = await createClient();
|
||||
|
||||
// Validate with Auth server (secure - always authenticates against Supabase)
|
||||
const {
|
||||
data: { user },
|
||||
} = await supabase.auth.getUser();
|
||||
|
||||
if (user) {
|
||||
console.log("🔐 [AUTH] User authenticated:", user.email);
|
||||
} else {
|
||||
console.log("🔐 [AUTH] No authenticated user");
|
||||
}
|
||||
|
||||
return user;
|
||||
});
|
||||
|
||||
// Get user data from database
|
||||
// Uses React's cache() for per-request deduplication
|
||||
// No cross-request caching due to serverless architecture
|
||||
// Fetch user data from all three tables in parallel, return the first match.
|
||||
// Wrapped in unstable_cache (Next.js Data Cache, shared across serverless instances)
|
||||
// keyed by email with a 60s TTL. React.cache() deduplicates within a single request.
|
||||
export const getUserData = cache(async (): Promise<AuthUserData | null> => {
|
||||
userDataCallCount++;
|
||||
console.log(`📊 [DB] getUserData called (count: ${userDataCallCount})`);
|
||||
|
||||
const user = await getUser();
|
||||
if (!user) return null;
|
||||
if (!user || !user.email) return null;
|
||||
|
||||
console.log("🗄️ [DB] Fetching user data from database for:", user.email);
|
||||
return unstable_cache(
|
||||
async (email: string, id: string): Promise<AuthUserData | null> => {
|
||||
const [userData, managerData, employeeData] = await Promise.all([
|
||||
prisma.user.findUnique({
|
||||
where: { id },
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
email: true,
|
||||
birthday: true,
|
||||
plz: true,
|
||||
city: true,
|
||||
street: true,
|
||||
houseNumber: true,
|
||||
gender: true,
|
||||
pbSrc: true,
|
||||
createdAt: true,
|
||||
},
|
||||
}),
|
||||
prisma.manager.findUnique({
|
||||
where: { id },
|
||||
select: {
|
||||
id: true,
|
||||
firstName: true,
|
||||
lastName: true,
|
||||
email: true,
|
||||
tel: true,
|
||||
pbSrc: true,
|
||||
createdAt: true,
|
||||
businesses: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
address: true,
|
||||
email: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
prisma.employee.findUnique({
|
||||
where: { email },
|
||||
select: {
|
||||
id: true,
|
||||
firstName: true,
|
||||
lastName: true,
|
||||
email: true,
|
||||
qualification: true,
|
||||
pbSrc: true,
|
||||
permissions: true,
|
||||
createdAt: true,
|
||||
createdBy: true,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
// Try to find in User table first
|
||||
const userData = await prisma.user.findUnique({
|
||||
where: { id: user.id },
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
email: true,
|
||||
birthday: true,
|
||||
plz: true,
|
||||
city: true,
|
||||
street: true,
|
||||
houseNumber: true,
|
||||
gender: true,
|
||||
pbSrc: true,
|
||||
createdAt: true,
|
||||
if (userData) {
|
||||
const userWithRole: UserData = { ...userData, role: "user" };
|
||||
return userWithRole;
|
||||
}
|
||||
|
||||
if (managerData) {
|
||||
const managerWithRole: ManagerData = { ...managerData, role: "manager" };
|
||||
return managerWithRole;
|
||||
}
|
||||
|
||||
if (employeeData) {
|
||||
const raw = employeeData.permissions as Record<string, unknown> | null;
|
||||
const empty = () => ({ view: false, create: false, edit: false, delete: false });
|
||||
|
||||
let permissions: EmployeeData["permissions"];
|
||||
|
||||
if (raw && ("canCreateCourses" in raw || "canCreateEmployees" in raw)) {
|
||||
// Backward-Kompatibilität: altes Format migrieren
|
||||
const old = raw as { canCreateCourses?: boolean; canCreateEmployees?: boolean };
|
||||
permissions = {
|
||||
employees: {
|
||||
view: old.canCreateEmployees ?? false,
|
||||
create: old.canCreateEmployees ?? false,
|
||||
edit: false,
|
||||
delete: false,
|
||||
},
|
||||
courses: {
|
||||
view: old.canCreateCourses ?? false,
|
||||
create: old.canCreateCourses ?? false,
|
||||
edit: false,
|
||||
delete: false,
|
||||
},
|
||||
rooms: empty(),
|
||||
};
|
||||
} else {
|
||||
const p = raw as {
|
||||
employees?: Partial<EmployeeData["permissions"]["employees"]>;
|
||||
courses?: Partial<EmployeeData["permissions"]["courses"]>;
|
||||
rooms?: Partial<EmployeeData["permissions"]["rooms"]>;
|
||||
} | null;
|
||||
permissions = {
|
||||
employees: {
|
||||
view: p?.employees?.view ?? false,
|
||||
create: p?.employees?.create ?? false,
|
||||
edit: p?.employees?.edit ?? false,
|
||||
delete: p?.employees?.delete ?? false,
|
||||
},
|
||||
courses: {
|
||||
view: p?.courses?.view ?? false,
|
||||
create: p?.courses?.create ?? false,
|
||||
edit: p?.courses?.edit ?? false,
|
||||
delete: p?.courses?.delete ?? false,
|
||||
},
|
||||
rooms: {
|
||||
view: p?.rooms?.view ?? false,
|
||||
create: p?.rooms?.create ?? false,
|
||||
edit: p?.rooms?.edit ?? false,
|
||||
delete: p?.rooms?.delete ?? false,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const employeeWithRole: EmployeeData = {
|
||||
...employeeData,
|
||||
role: "employee",
|
||||
permissions,
|
||||
createdBy: employeeData.createdBy,
|
||||
};
|
||||
return employeeWithRole;
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
});
|
||||
|
||||
if (userData) {
|
||||
console.log("✅ [DB] User data fetched:", userData.name);
|
||||
const userWithRole: UserData = { ...userData, role: "user" };
|
||||
return userWithRole;
|
||||
}
|
||||
|
||||
// If not found in User table, try Manager table
|
||||
const managerData = await prisma.manager.findUnique({
|
||||
where: { id: user.id },
|
||||
select: {
|
||||
id: true,
|
||||
firstName: true,
|
||||
lastName: true,
|
||||
email: true,
|
||||
tel: true,
|
||||
pbSrc: true,
|
||||
createdAt: true,
|
||||
businesses: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
address: true,
|
||||
email: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (managerData) {
|
||||
console.log(
|
||||
"✅ [DB] Manager data fetched:",
|
||||
`${managerData.firstName} ${managerData.lastName}`
|
||||
);
|
||||
const managerWithRole: ManagerData = { ...managerData, role: "manager" };
|
||||
return managerWithRole;
|
||||
}
|
||||
|
||||
// Try Employee table — match by email since Supabase ID is not stored in Employee
|
||||
if (!user.email) {
|
||||
console.log("⚠️ [DB] User has no email, cannot lookup employee");
|
||||
return null;
|
||||
}
|
||||
|
||||
const employeeData = await prisma.employee.findUnique({
|
||||
where: { email: user.email },
|
||||
select: {
|
||||
id: true,
|
||||
firstName: true,
|
||||
lastName: true,
|
||||
email: true,
|
||||
qualification: true,
|
||||
pbSrc: true,
|
||||
permissions: true,
|
||||
createdAt: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (employeeData) {
|
||||
console.log(
|
||||
"✅ [DB] Employee data fetched:",
|
||||
`${employeeData.firstName} ${employeeData.lastName}`
|
||||
);
|
||||
const raw = employeeData.permissions as Record<string, unknown> | null;
|
||||
const empty = () => ({ view: false, create: false, edit: false, delete: false });
|
||||
|
||||
let permissions: EmployeeData["permissions"];
|
||||
|
||||
if (raw && ("canCreateCourses" in raw || "canCreateEmployees" in raw)) {
|
||||
// Backward-Kompatibilität: altes Format migrieren
|
||||
const old = raw as { canCreateCourses?: boolean; canCreateEmployees?: boolean };
|
||||
permissions = {
|
||||
employees: {
|
||||
view: old.canCreateEmployees ?? false,
|
||||
create: old.canCreateEmployees ?? false,
|
||||
edit: false,
|
||||
delete: false,
|
||||
},
|
||||
courses: {
|
||||
view: old.canCreateCourses ?? false,
|
||||
create: old.canCreateCourses ?? false,
|
||||
edit: false,
|
||||
delete: false,
|
||||
},
|
||||
rooms: empty(),
|
||||
};
|
||||
} else {
|
||||
const p = raw as {
|
||||
employees?: Partial<EmployeeData["permissions"]["employees"]>;
|
||||
courses?: Partial<EmployeeData["permissions"]["courses"]>;
|
||||
rooms?: Partial<EmployeeData["permissions"]["rooms"]>;
|
||||
} | null;
|
||||
permissions = {
|
||||
employees: {
|
||||
view: p?.employees?.view ?? false,
|
||||
create: p?.employees?.create ?? false,
|
||||
edit: p?.employees?.edit ?? false,
|
||||
delete: p?.employees?.delete ?? false,
|
||||
},
|
||||
courses: {
|
||||
view: p?.courses?.view ?? false,
|
||||
create: p?.courses?.create ?? false,
|
||||
edit: p?.courses?.edit ?? false,
|
||||
delete: p?.courses?.delete ?? false,
|
||||
},
|
||||
rooms: {
|
||||
view: p?.rooms?.view ?? false,
|
||||
create: p?.rooms?.create ?? false,
|
||||
edit: p?.rooms?.edit ?? false,
|
||||
delete: p?.rooms?.delete ?? false,
|
||||
},
|
||||
};
|
||||
["user-data", user.email],
|
||||
{
|
||||
tags: [`user-data-${user.email}`],
|
||||
revalidate: 60,
|
||||
}
|
||||
|
||||
const employeeWithRole: EmployeeData = {
|
||||
...employeeData,
|
||||
role: "employee",
|
||||
permissions,
|
||||
};
|
||||
return employeeWithRole;
|
||||
}
|
||||
|
||||
console.log("⚠️ [DB] No user, manager or employee found for:", user.email);
|
||||
return null;
|
||||
)(user.email, user.id);
|
||||
});
|
||||
|
||||
export async function requireAuth() {
|
||||
|
|
|
|||
|
|
@ -60,5 +60,7 @@ export async function middleware(request: NextRequest) {
|
|||
}
|
||||
|
||||
export const config = {
|
||||
matcher: ["/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)"],
|
||||
matcher: [
|
||||
"/((?!_next/static|_next/data|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)",
|
||||
],
|
||||
};
|
||||
|
|
|
|||
|
|
@ -62,11 +62,7 @@ export async function createCourse(data: CourseFormData, status: "draft" | "publ
|
|||
const validatedData = validation.data;
|
||||
|
||||
// Schritt 5: Manager-ID ermitteln (Employee erbt createdBy vom eigenen Datensatz)
|
||||
let creatorId = userData.id;
|
||||
if (isEmployee(userData)) {
|
||||
const selfRecord = await prisma.employee.findUnique({ where: { email: userData.email } });
|
||||
creatorId = selfRecord?.createdBy ?? userData.id;
|
||||
}
|
||||
const creatorId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
|
||||
// Schritt 6: Kurs in der Datenbank erstellen
|
||||
const course = await prisma.course.create({
|
||||
|
|
@ -175,11 +171,7 @@ export async function getMyCourses(options?: { dateFrom?: Date; dateTo?: Date })
|
|||
}
|
||||
|
||||
// Step 3: Manager-ID ermitteln (Employee erbt createdBy vom eigenen Datensatz)
|
||||
let managerId = userData.id;
|
||||
if (isEmployee(userData)) {
|
||||
const selfRecord = await prisma.employee.findUnique({ where: { email: userData.email } });
|
||||
managerId = selfRecord?.createdBy ?? userData.id;
|
||||
}
|
||||
const managerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
|
||||
// Step 4: Build the where clause with optional date filtering
|
||||
const whereClause: Prisma.CourseWhereInput = {
|
||||
|
|
@ -254,11 +246,7 @@ export async function getCourseById(courseId: string) {
|
|||
}
|
||||
|
||||
// Schritt 3: Effektive Manager-ID ermitteln
|
||||
let managerId = userData.id;
|
||||
if (isEmployee(userData)) {
|
||||
const selfRecord = await prisma.employee.findUnique({ where: { email: userData.email } });
|
||||
managerId = selfRecord?.createdBy ?? userData.id;
|
||||
}
|
||||
const managerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
|
||||
// Schritt 4: Kurs aus der Datenbank abrufen
|
||||
const course = await prisma.course.findUnique({
|
||||
|
|
@ -334,11 +322,7 @@ export async function updateCourse(
|
|||
}
|
||||
|
||||
// Schritt 4: Effektive Manager-ID ermitteln
|
||||
let managerId = userData.id;
|
||||
if (isEmployee(userData)) {
|
||||
const selfRecord = await prisma.employee.findUnique({ where: { email: userData.email } });
|
||||
managerId = selfRecord?.createdBy ?? userData.id;
|
||||
}
|
||||
const managerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
|
||||
// Schritt 5: Kurs aus der Datenbank abrufen
|
||||
const existingCourse = await prisma.course.findUnique({
|
||||
|
|
@ -445,11 +429,7 @@ export async function deleteCourse(courseId: string) {
|
|||
}
|
||||
|
||||
// Schritt 3: Effektive Manager-ID ermitteln
|
||||
let managerId = userData.id;
|
||||
if (isEmployee(userData)) {
|
||||
const selfRecord = await prisma.employee.findUnique({ where: { email: userData.email } });
|
||||
managerId = selfRecord?.createdBy ?? userData.id;
|
||||
}
|
||||
const managerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
|
||||
// Schritt 4: Kurs aus der Datenbank abrufen
|
||||
const course = await prisma.course.findUnique({
|
||||
|
|
@ -507,11 +487,7 @@ export async function getMySportTypes() {
|
|||
return { success: false, error: "Unauthorized", sports: [] };
|
||||
}
|
||||
|
||||
let managerId = userData.id;
|
||||
if (isEmployee(userData)) {
|
||||
const selfRecord = await prisma.employee.findUnique({ where: { email: userData.email } });
|
||||
managerId = selfRecord?.createdBy ?? userData.id;
|
||||
}
|
||||
const managerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
|
||||
const courses = await prisma.course.findMany({
|
||||
where: { createdBy: managerId },
|
||||
|
|
|
|||
|
|
@ -12,7 +12,12 @@ import { prisma } from "@/src/lib/prisma";
|
|||
import { getUserData, isManager, isEmployee } from "@/src/lib/auth/getUser";
|
||||
import { createAdminClient } from "@/src/lib/supabase/admin";
|
||||
import { employeeSchema, type EmployeeFormData } from "../schemas/employee-schema";
|
||||
import { revalidatePath } from "next/cache";
|
||||
import { revalidatePath, revalidateTag } from "next/cache";
|
||||
|
||||
function invalidateUserDataCache(email: string) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(revalidateTag as any)(`user-data-${email}`);
|
||||
}
|
||||
import { randomBytes } from "crypto";
|
||||
import { sendMail } from "@/src/lib/mail/nodemailer";
|
||||
import { generateOnboardingEmail } from "@/src/lib/mail/templates/employee-onboarding";
|
||||
|
|
@ -124,11 +129,7 @@ export async function createEmployee(data: EmployeeFormData, status: "draft" | "
|
|||
}
|
||||
|
||||
// Schritt 7: Manager-ID ermitteln (Employee erbt createdBy vom eigenen Datensatz)
|
||||
let managerId = userData.id;
|
||||
if (isEmployee(userData)) {
|
||||
const selfRecord = await prisma.employee.findUnique({ where: { email: userData.email } });
|
||||
managerId = selfRecord?.createdBy ?? userData.id;
|
||||
}
|
||||
const managerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
|
||||
// Schritt 8: Berechtigungen auf Caller-Ceiling begrenzen (Privilege-Escalation verhindern)
|
||||
const finalPermissions = isEmployee(userData)
|
||||
|
|
@ -215,11 +216,7 @@ export async function getMyTrainers() {
|
|||
};
|
||||
}
|
||||
|
||||
let managerId = userData.id;
|
||||
if (isEmployee(userData)) {
|
||||
const selfRecord = await prisma.employee.findUnique({ where: { email: userData.email } });
|
||||
managerId = selfRecord?.createdBy ?? userData.id;
|
||||
}
|
||||
const managerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
|
||||
const employees = await prisma.employee.findMany({
|
||||
where: {
|
||||
|
|
@ -286,8 +283,7 @@ export async function getMyEmployees() {
|
|||
whereClause = { createdBy: userData.id };
|
||||
} else {
|
||||
// Employee: eigene Manager-ID ermitteln, dann alle unter diesem Manager anzeigen (außer sich selbst)
|
||||
const selfRecord = await prisma.employee.findUnique({ where: { email: userData.email } });
|
||||
const managerId = selfRecord?.createdBy;
|
||||
const managerId = userData.createdBy;
|
||||
whereClause = { createdBy: managerId, NOT: { email: userData.email } };
|
||||
}
|
||||
const employees = await prisma.employee.findMany({
|
||||
|
|
@ -439,11 +435,7 @@ export async function updateEmployee(
|
|||
}
|
||||
|
||||
// Schritt 6: Überprüfen, ob der Benutzer der Besitzer des Mitarbeiters ist
|
||||
let ownerManagerId = userData.id;
|
||||
if (isEmployee(userData)) {
|
||||
const selfRecord = await prisma.employee.findUnique({ where: { email: userData.email } });
|
||||
ownerManagerId = selfRecord?.createdBy ?? userData.id;
|
||||
}
|
||||
const ownerManagerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
if (existingEmployee.createdBy !== ownerManagerId) {
|
||||
return {
|
||||
success: false,
|
||||
|
|
@ -525,6 +517,7 @@ export async function updateEmployee(
|
|||
// Schritt 11: Next.js Cache invalidieren
|
||||
revalidatePath("/employee");
|
||||
revalidatePath(`/employee/edit/${employeeId}`);
|
||||
invalidateUserDataCache(validatedData.email);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
|
|
@ -571,11 +564,7 @@ export async function getMyEmployeeRoles() {
|
|||
}
|
||||
|
||||
// Schritt 3: Effektive Manager-ID ermitteln
|
||||
let managerId = userData.id;
|
||||
if (isEmployee(userData)) {
|
||||
const selfRecord = await prisma.employee.findUnique({ where: { email: userData.email } });
|
||||
managerId = selfRecord?.createdBy ?? userData.id;
|
||||
}
|
||||
const managerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
|
||||
// Schritt 4: Alle Mitarbeiter des Managers abrufen (nur roles Feld)
|
||||
const employees = await prisma.employee.findMany({
|
||||
|
|
@ -660,11 +649,7 @@ export async function deleteEmployee(employeeId: string) {
|
|||
}
|
||||
|
||||
// Schritt 5: Überprüfen, ob der Benutzer der Besitzer des Mitarbeiters ist
|
||||
let ownerManagerId = userData.id;
|
||||
if (isEmployee(userData)) {
|
||||
const selfRecord = await prisma.employee.findUnique({ where: { email: userData.email } });
|
||||
ownerManagerId = selfRecord?.createdBy ?? userData.id;
|
||||
}
|
||||
const ownerManagerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
if (employee.createdBy !== ownerManagerId) {
|
||||
return {
|
||||
success: false,
|
||||
|
|
@ -694,6 +679,7 @@ export async function deleteEmployee(employeeId: string) {
|
|||
|
||||
// Schritt 8: Next.js Cache invalidieren
|
||||
revalidatePath("/employee");
|
||||
invalidateUserDataCache(employee.email);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
|
|
@ -840,6 +826,8 @@ export async function completeEmployeeOnboarding(
|
|||
};
|
||||
}
|
||||
|
||||
invalidateUserDataCache(employee.email);
|
||||
|
||||
// Manager-Bestätigungs-E-Mail senden
|
||||
if (employee.createdBy) {
|
||||
const manager = await prisma.manager.findUnique({
|
||||
|
|
|
|||
|
|
@ -59,11 +59,7 @@ export async function createRoom(data: RoomFormData) {
|
|||
const validatedData = validation.data;
|
||||
|
||||
// Schritt 5: Manager-ID ermitteln (Employee erbt createdBy vom eigenen Datensatz)
|
||||
let creatorId = userData.id;
|
||||
if (isEmployee(userData)) {
|
||||
const selfRecord = await prisma.employee.findUnique({ where: { email: userData.email } });
|
||||
creatorId = selfRecord?.createdBy ?? userData.id;
|
||||
}
|
||||
const creatorId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
|
||||
// Schritt 6: Raum in der Datenbank erstellen
|
||||
const room = await prisma.room.create({
|
||||
|
|
@ -147,11 +143,7 @@ export async function getMyRooms() {
|
|||
}
|
||||
|
||||
// Schritt 3: Manager-ID ermitteln (Employee erbt createdBy vom eigenen Datensatz)
|
||||
let managerId = userData.id;
|
||||
if (isEmployee(userData)) {
|
||||
const selfRecord = await prisma.employee.findUnique({ where: { email: userData.email } });
|
||||
managerId = selfRecord?.createdBy ?? userData.id;
|
||||
}
|
||||
const managerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
|
||||
// Schritt 4: Räume abrufen, die von diesem Manager erstellt wurden
|
||||
const rooms = await prisma.room.findMany({
|
||||
|
|
@ -203,11 +195,7 @@ export async function getRoomById(roomId: string) {
|
|||
}
|
||||
|
||||
// Schritt 3: Effektive Manager-ID ermitteln
|
||||
let managerId = userData.id;
|
||||
if (isEmployee(userData)) {
|
||||
const selfRecord = await prisma.employee.findUnique({ where: { email: userData.email } });
|
||||
managerId = selfRecord?.createdBy ?? userData.id;
|
||||
}
|
||||
const managerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
|
||||
// Schritt 4: Raum aus der Datenbank abrufen
|
||||
const room = await prisma.room.findUnique({
|
||||
|
|
@ -279,11 +267,7 @@ export async function updateRoom(roomId: string, data: RoomFormData) {
|
|||
}
|
||||
|
||||
// Schritt 4: Effektive Manager-ID ermitteln
|
||||
let managerId = userData.id;
|
||||
if (isEmployee(userData)) {
|
||||
const selfRecord = await prisma.employee.findUnique({ where: { email: userData.email } });
|
||||
managerId = selfRecord?.createdBy ?? userData.id;
|
||||
}
|
||||
const managerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
|
||||
// Schritt 5: Raum aus der Datenbank abrufen
|
||||
const existingRoom = await prisma.room.findUnique({
|
||||
|
|
@ -372,11 +356,7 @@ export async function deleteRoom(roomId: string) {
|
|||
}
|
||||
|
||||
// Schritt 3: Effektive Manager-ID ermitteln
|
||||
let managerId = userData.id;
|
||||
if (isEmployee(userData)) {
|
||||
const selfRecord = await prisma.employee.findUnique({ where: { email: userData.email } });
|
||||
managerId = selfRecord?.createdBy ?? userData.id;
|
||||
}
|
||||
const managerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
|
||||
// Schritt 4: Raum aus der Datenbank abrufen
|
||||
const room = await prisma.room.findUnique({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue