import { sql } from "drizzle-orm"; import { authorize, rows, TimeService } from "../../modules/time-v2/service"; import { timeActor, uuid } from "./time-v2"; import { FastifyInstance } from 'fastify' import { StaffTimeEntryConnect } from '../../types/staff' import { asc, eq } from "drizzle-orm"; import { stafftimenetryconnects } from "../../../db/schema"; export default async function staffTimeConnectRoutes(server: FastifyInstance) { server.addHook('preHandler', async (req, reply) => { try { const a = timeActor(req), params = req.params as any; const id = uuid(params.id || params.connectId); const [owner] = await rows(server.db, params.id ? sql`SELECT e.user_id,e.id FROM staff_time_entries e WHERE e.id=${id}::uuid AND e.tenant_id=${a.tenant}` : sql`SELECT e.user_id,e.id FROM staff_time_entry_connects c JOIN staff_time_entries e ON e.id=c.time_entry_id WHERE c.id=${id}::uuid AND e.tenant_id=${a.tenant}`); if (!owner) return reply.code(404).send({error:'Zeiteintrag nicht gefunden.'}); authorize(a,owner.user_id,req.method === 'GET' ? 'read' : 'write'); const service = new TimeService(server.db); if (await service.active(a,owner.user_id)) { if (req.method !== 'GET') return reply.code(409).send({error:'Projektzeiten unter 2.0 → Zeiterfassung bearbeiten.'}); const [origin] = await rows(server.db,sql`SELECT span_id FROM staff_time_span_origins WHERE tenant_id=${a.tenant} AND source_kind='entry' AND source_id=${owner.id}::uuid`); const span = origin ? await service.get(a,origin.span_id) : null; return reply.send((span?.projects || []).map(p => ({...p,stopped_at:p.ended_at}))); } } catch (e:any) { return reply.code(e.statusCode || 400).send({error:e.message}); } }); // ▶ Connect anlegen server.post<{ Params: { id: string }, Body: Omit }>( '/staff/time/:id/connects', async (req, reply) => { const { id } = req.params const { started_at, stopped_at, project_id, notes } = req.body const parsedProjectId = project_id ? Number(project_id) : null const data = await server.db .insert(stafftimenetryconnects) .values({ stafftimeentry: id, started_at: new Date(started_at), stopped_at: new Date(stopped_at), project_id: parsedProjectId, notes }) .returning() return reply.send(data[0]) } ) // ▶ Connects abrufen server.get<{ Params: { id: string } }>( '/staff/time/:id/connects', async (req, reply) => { const { id } = req.params const data = await server.db .select() .from(stafftimenetryconnects) .where(eq(stafftimenetryconnects.stafftimeentry, id)) .orderBy(asc(stafftimenetryconnects.started_at)) return reply.send(data) } ) // ▶ Connect aktualisieren server.patch<{ Params: { connectId: string }, Body: Partial }>( '/staff/time/connects/:connectId', async (req, reply) => { const { connectId } = req.params const patchData = Object.fromEntries(Object.entries(req.body).filter(([key]) => ['started_at', 'stopped_at', 'project_id', 'notes'].includes(key))) as any if (patchData.started_at) patchData.started_at = new Date(patchData.started_at) if (patchData.stopped_at) patchData.stopped_at = new Date(patchData.stopped_at) if (patchData.project_id !== undefined) { patchData.project_id = patchData.project_id ? Number(patchData.project_id) : null } const data = await server.db .update(stafftimenetryconnects) .set({ ...patchData, updated_at: new Date() }) .where(eq(stafftimenetryconnects.id, connectId)) .returning() return reply.send(data[0]) } ) // ▶ Connect löschen server.delete<{ Params: { connectId: string } }>( '/staff/time/connects/:connectId', async (req, reply) => { const { connectId } = req.params await server.db .delete(stafftimenetryconnects) .where(eq(stafftimenetryconnects.id, connectId)) return reply.send({ success: true }) } ) }