Files
FEDEO/backend/src/routes/staff/timeconnects.ts

104 lines
4.6 KiB
TypeScript

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<StaffTimeEntryConnect, 'id' | 'time_entry_id'> }>(
'/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<StaffTimeEntryConnect> }>(
'/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 })
}
)
}