import { ContractTaskStatus } from '@prisma/client'; import prisma from '../lib/prisma.js'; export interface ContractTaskFilters { contractId: number; status?: ContractTaskStatus; visibleInPortal?: boolean; // Für Kundenportal: Zeige Tasks die entweder sichtbar sind ODER vom Kunden erstellt wurden customerPortalEmails?: string[]; } export async function getTasksByContract(filters: ContractTaskFilters) { // eslint-disable-next-line @typescript-eslint/no-explicit-any const where: any = { contractId: filters.contractId, }; if (filters.status) { where.status = filters.status; } // Spezielle Logik für Kundenportal if (filters.customerPortalEmails && filters.customerPortalEmails.length > 0) { // Zeige Tasks die: // 1. visibleInPortal = true ODER // 2. vom Kunden selbst erstellt wurden (createdBy in customerPortalEmails) where.OR = [ { visibleInPortal: true }, { createdBy: { in: filters.customerPortalEmails } }, ]; } else if (filters.visibleInPortal !== undefined) { where.visibleInPortal = filters.visibleInPortal; } return prisma.contractTask.findMany({ where, include: { subtasks: { orderBy: { createdAt: 'asc' }, }, }, orderBy: { createdAt: 'desc' }, }); } export async function getTaskById(id: number) { return prisma.contractTask.findUnique({ where: { id }, }); } export async function createTask(data: { contractId: number; title: string; description?: string; visibleInPortal?: boolean; createdBy?: string; }) { return prisma.contractTask.create({ data: { contractId: data.contractId, title: data.title, description: data.description, visibleInPortal: data.visibleInPortal ?? false, createdBy: data.createdBy, }, }); } export async function updateTask( id: number, data: { title?: string; description?: string; visibleInPortal?: boolean; } ) { return prisma.contractTask.update({ where: { id }, data, }); } export async function completeTask(id: number) { return prisma.contractTask.update({ where: { id }, data: { status: 'COMPLETED', completedAt: new Date(), }, }); } export async function reopenTask(id: number) { return prisma.contractTask.update({ where: { id }, data: { status: 'OPEN', completedAt: null, }, }); } export async function deleteTask(id: number) { return prisma.contractTask.delete({ where: { id }, }); } // ==================== SUBTASKS ==================== export async function createSubtask(data: { taskId: number; title: string; createdBy?: string }) { return prisma.contractTaskSubtask.create({ data: { taskId: data.taskId, title: data.title, createdBy: data.createdBy, }, }); } export async function updateSubtask(id: number, data: { title?: string }) { return prisma.contractTaskSubtask.update({ where: { id }, data, }); } export async function completeSubtask(id: number) { // Complete the subtask const subtask = await prisma.contractTaskSubtask.update({ where: { id }, data: { status: 'COMPLETED', completedAt: new Date(), }, }); // Check if all subtasks of the parent task are now completed const remainingOpenSubtasks = await prisma.contractTaskSubtask.count({ where: { taskId: subtask.taskId, status: 'OPEN', }, }); // If no open subtasks remain, automatically complete the parent task if (remainingOpenSubtasks === 0) { await prisma.contractTask.update({ where: { id: subtask.taskId }, data: { status: 'COMPLETED', completedAt: new Date(), }, }); } return subtask; } export async function reopenSubtask(id: number) { // Reopen the subtask const subtask = await prisma.contractTaskSubtask.update({ where: { id }, data: { status: 'OPEN', completedAt: null, }, }); // If the parent task was completed, reopen it as well const parentTask = await prisma.contractTask.findUnique({ where: { id: subtask.taskId }, }); if (parentTask?.status === 'COMPLETED') { await prisma.contractTask.update({ where: { id: subtask.taskId }, data: { status: 'OPEN', completedAt: null, }, }); } return subtask; } export async function deleteSubtask(id: number) { return prisma.contractTaskSubtask.delete({ where: { id }, }); } export async function getSubtaskById(id: number) { return prisma.contractTaskSubtask.findUnique({ where: { id }, include: { task: true }, }); } // ==================== ALL TASKS ==================== export interface AllTasksFilters { status?: ContractTaskStatus; customerId?: number; // Für Kundenportal: Nur Tasks für erlaubte Verträge und sichtbare/eigene Tasks customerPortalCustomerIds?: number[]; customerPortalEmails?: string[]; } export async function getAllTasks(filters: AllTasksFilters) { // eslint-disable-next-line @typescript-eslint/no-explicit-any const where: any = {}; if (filters.status) { where.status = filters.status; } // Für Kundenportal: Filter auf erlaubte Verträge + Sichtbarkeit if (filters.customerPortalCustomerIds && filters.customerPortalCustomerIds.length > 0) { where.contract = { customerId: { in: filters.customerPortalCustomerIds }, }; // Zeige nur sichtbare Tasks ODER vom Kunden erstellte if (filters.customerPortalEmails && filters.customerPortalEmails.length > 0) { where.OR = [ { visibleInPortal: true }, { createdBy: { in: filters.customerPortalEmails } }, ]; } else { where.visibleInPortal = true; } } else if (filters.customerId) { // Für Mitarbeiter: Optional nach Kunde filtern where.contract = { customerId: filters.customerId, }; } return prisma.contractTask.findMany({ where, include: { subtasks: { orderBy: { createdAt: 'asc' }, }, contract: { select: { id: true, contractNumber: true, customerId: true, customer: { select: { id: true, firstName: true, lastName: true, companyName: true, customerNumber: true, }, }, provider: { select: { id: true, name: true, }, }, tariff: { select: { id: true, name: true, }, }, providerName: true, tariffName: true, }, }, }, orderBy: { createdAt: 'desc' }, }); } export async function getTaskStats(filters: AllTasksFilters) { // eslint-disable-next-line @typescript-eslint/no-explicit-any const where: any = { status: 'OPEN', }; // Für Kundenportal: Filter auf erlaubte Verträge + Sichtbarkeit if (filters.customerPortalCustomerIds && filters.customerPortalCustomerIds.length > 0) { where.contract = { customerId: { in: filters.customerPortalCustomerIds }, }; // Zeige nur sichtbare Tasks ODER vom Kunden erstellte if (filters.customerPortalEmails && filters.customerPortalEmails.length > 0) { where.OR = [ { visibleInPortal: true }, { createdBy: { in: filters.customerPortalEmails } }, ]; } else { where.visibleInPortal = true; } } else if (filters.customerId) { where.contract = { customerId: filters.customerId, }; } const openCount = await prisma.contractTask.count({ where }); return { openCount }; }