import { aenderungEingabe } from '@/lib/api' import type { Prisma } from '@/generated/prisma/client' import { db } from '@/server/db' import { abgelehnt, apiProtokoll, daten, rumpfLesen, wache } from '@/server/api/wache' import { jetzt } from '@/server/zeitgeber' export const dynamic = 'force-dynamic' /** * Eine einzelne Aufgabe lesen und ändern. * * Ändern heißt: Titel, Notiz, Fälligkeit, Priorität, Aufwand — und abhaken. * Bereich und Projekt bleiben außen vor; die Einordnung ist Sache dessen, der * plant, nicht dessen, der meldet. */ const AUSWAHL = { id: true, titel: true, notiz: true, status: true, prioritaet: true, aufwandMinuten: true, faelligAm: true, quelle: true, quelleRef: true, quelleUrl: true, erstelltAm: true, bereich: { select: { name: true } }, projekt: { select: { name: true } }, } as const type Zeile = { id: string titel: string notiz: string | null status: string prioritaet: number aufwandMinuten: number | null faelligAm: Date | null quelle: string quelleRef: string | null quelleUrl: string | null erstelltAm: Date bereich: { name: string } | null projekt: { name: string } | null } function alsAntwort(a: Zeile) { return { id: a.id, titel: a.titel, notiz: a.notiz, status: a.status, prioritaet: a.prioritaet, aufwandMinuten: a.aufwandMinuten, faelligAm: a.faelligAm ? a.faelligAm.toISOString() : null, quelle: a.quelle, ref: a.quelleRef, url: a.quelleUrl, erstelltAm: a.erstelltAm.toISOString(), bereich: a.bereich?.name ?? null, projekt: a.projekt?.name ?? null, } } export async function GET( anfrage: Request, { params }: { params: Promise<{ id: string }> }, ) { const geprueft = await wache(anfrage, 'lesen') if (!geprueft.ok) return geprueft.antwort const { id } = await params const aufgabe = await db.aufgabe.findUnique({ where: { id }, select: AUSWAHL }) if (!aufgabe) return abgelehnt('nichtGefunden') return daten(alsAntwort(aufgabe)) } export async function PATCH( anfrage: Request, { params }: { params: Promise<{ id: string }> }, ) { const geprueft = await wache(anfrage, 'schreiben') if (!geprueft.ok) return geprueft.antwort const { aufrufer } = geprueft const { id } = await params const rumpf = await rumpfLesen(anfrage) if (rumpf === undefined) return abgelehnt('ungueltig') const gelesen = aenderungEingabe.safeParse(rumpf) if (!gelesen.success) { return daten( { fehler: 'Die Anfrage war fehlerhaft.', felder: gelesen.error.issues.map((f) => ({ feld: f.path.join('.'), grund: f.message, })), }, 400, ) } const vorhanden = await db.aufgabe.findUnique({ where: { id }, select: { id: true, status: true }, }) if (!vorhanden) return abgelehnt('nichtGefunden') const { erledigt, faelligAm, titel, notiz, prioritaet, aufwandMinuten } = gelesen.data const zeitpunkt = jetzt() // Feld fuer Feld statt Spread: Mit exactOptionalPropertyTypes ist ein // gesetztes "undefined" etwas anderes als ein fehlendes Feld, und Prisma // wuerde daraus einen Schreibversuch machen. const werte: Prisma.AufgabeUpdateInput = {} if (titel !== undefined) werte.titel = titel if (notiz !== undefined) werte.notiz = notiz if (prioritaet !== undefined) werte.prioritaet = prioritaet if (aufwandMinuten !== undefined) werte.aufwandMinuten = aufwandMinuten if (faelligAm !== undefined) { werte.faelligAm = faelligAm === null ? null : new Date(faelligAm) } if (erledigt !== undefined) { werte.status = erledigt ? 'ERLEDIGT' : 'OFFEN' werte.erledigtAm = erledigt ? zeitpunkt : null } const aufgabe = await db.aufgabe.update({ where: { id: vorhanden.id }, data: werte, select: AUSWAHL, }) await apiProtokoll(aufrufer, 'api.geaendert', aufgabe.id, { felder: Object.keys(gelesen.data), }) return daten(alsAntwort(aufgabe)) }