This commit is contained in:
2025-12-08 12:15:20 +01:00
parent 1d3bf94b88
commit 428a002e9f
7 changed files with 495 additions and 427 deletions

View File

@@ -1,143 +1,173 @@
import { FastifyInstance } from 'fastify'
import { StaffTimeEntry } from '../../types/staff'
import { FastifyInstance } from "fastify"
import {
stafftimeentries,
stafftimenetryconnects
} from "../../../db/schema"
import {
eq,
and,
gte,
lte,
desc
} from "drizzle-orm"
export default async function staffTimeRoutes(server: FastifyInstance) {
// -------------------------------------------------------------
// ▶ Neue Zeit starten
server.post(
'/staff/time',
async (req, reply) => {
const { started_at, stopped_at, type = 'work', description, user_id } = req.body as any
// -------------------------------------------------------------
server.post("/staff/time", async (req, reply) => {
try {
const { user_id, ...rest } = req.body as any
const userId = req.user.user_id
const tenantId = req.user.tenant_id
let dataToInsert = {
const newEntry = {
tenant_id: tenantId,
user_id: user_id ? user_id : userId,
// @ts-ignore
...req.body
user_id: user_id || userId,
...rest
}
const { data, error } = await server.supabase
.from('staff_time_entries')
.insert([dataToInsert])
.select()
.maybeSingle()
const [created] = await server.db
.insert(stafftimeentries)
.values(newEntry)
.returning()
if (error) return reply.code(400).send({ error: error.message })
return reply.send(data)
return created
} catch (err: any) {
console.error(err)
return reply.code(400).send({ error: err.message })
}
)
// ▶ Zeit stoppen
server.put<{ Params: { id: string }, Body: { stopped_at: string } }>(
'/staff/time/:id/stop',
async (req, reply) => {
const { id } = req.params
const { stopped_at } = req.body
const { data, error } = await server.supabase
.from('staff_time_entries')
.update({ stopped_at, updated_at: new Date().toISOString() })
.eq('id', id)
.select()
.maybeSingle()
if (error) return reply.code(400).send({ error: error.message })
return reply.send(data)
}
)
// ▶ Liste aller Zeiten
server.get<{
Querystring: {
from?: string
to?: string
type?: string
user_id?: string
}
}>('/staff/time', async (req, reply) => {
const { from, to, type, user_id } = req.query
const { user_id: currentUserId, tenant_id } = req.user
// 🧩 Basis-Query für den Tenant
let query = server.supabase
.from('staff_time_entries')
.select('*')
.eq('tenant_id', tenant_id)
.order('started_at', { ascending: false })
// 🔒 Zugriffsbeschränkung: nur eigene Zeiten, außer Berechtigung erlaubt mehr
if (!req.hasPermission('staff.time.read_all')) {
query = query.eq('user_id', currentUserId)
} else if (user_id) {
// falls explizit user_id angegeben wurde
query = query.eq('user_id', user_id)
}
// 📅 Zeitfilter
if (from) query = query.gte('started_at', from)
if (to) query = query.lte('started_at', to)
if (type) query = query.eq('type', type)
const { data, error } = await query
if (error) return reply.code(400).send({ error: error.message })
return reply.send(data)
})
// -------------------------------------------------------------
// ▶ Zeit stoppen
// -------------------------------------------------------------
server.put("/staff/time/:id/stop", async (req, reply) => {
try {
const { id } = req.params as any
const { stopped_at } = req.body as any
// ▶ Einzelne Zeit abrufen (inkl. Connects)
server.get<{ Params: { id: string } }>(
'/staff/time/:id',
async (req, reply) => {
const { id } = req.params
const [updated] = await server.db
.update(stafftimeentries)
.set({
stopped_at,
updated_at: new Date()
})
.where(eq(stafftimeentries.id, id))
.returning()
const { data, error } = await server.supabase
.from('staff_time_entries')
.select(`
*,
staff_time_entry_connects(*)
`)
.eq('id', id)
.maybeSingle()
if (error) return reply.code(400).send({ error: error.message })
return reply.send(data)
return updated
} catch (err) {
return reply.code(400).send({ error: (err as Error).message })
}
)
})
// ▶ Zeit bearbeiten
server.put<{ Params: { id: string }, Body: Partial<StaffTimeEntry> }>(
'/staff/time/:id',
async (req, reply) => {
const { id } = req.params
// -------------------------------------------------------------
// ▶ Liste aller Zeiten
// -------------------------------------------------------------
server.get("/staff/time", async (req, reply) => {
try {
const { from, to, type, user_id } = req.query as any
const { tenant_id, user_id: currentUserId } = req.user
const { data, error } = await server.supabase
.from('staff_time_entries')
.update({ ...req.body, updated_at: new Date().toISOString() })
.eq('id', id)
let where = and(eq(stafftimeentries.tenant_id, tenant_id))
// Zugriffsbeschränkung
if (!req.hasPermission("staff.time.read_all")) {
where = and(where, eq(stafftimeentries.user_id, currentUserId))
} else if (user_id) {
where = and(where, eq(stafftimeentries.user_id, user_id))
}
if (from) where = and(where, gte(stafftimeentries.started_at, from))
if (to) where = and(where, lte(stafftimeentries.started_at, to))
if (type) where = and(where, eq(stafftimeentries.type, type))
const rows = await server.db
.select()
.maybeSingle()
.from(stafftimeentries)
.where(where)
.orderBy(desc(stafftimeentries.started_at))
if (error) return reply.code(400).send({ error: error.message })
return reply.send(data)
return rows
} catch (err) {
console.error(err)
return reply.code(400).send({ error: (err as Error).message })
}
)
})
// -------------------------------------------------------------
// ▶ Einzelne Zeit (inkl. Connects)
// -------------------------------------------------------------
server.get("/staff/time/:id", async (req, reply) => {
try {
const { id } = req.params as any
const rows = await server.db
.select()
.from(stafftimeentries)
.where(eq(stafftimeentries.id, id))
.limit(1)
if (!rows.length) return reply.code(404).send({ error: "Not found" })
const entry = rows[0]
const connects = await server.db
.select()
.from(stafftimenetryconnects)
.where(eq(stafftimenetryconnects.stafftimeentry, id))
return {
...entry,
staff_time_entry_connects: connects
}
} catch (err) {
return reply.code(400).send({ error: (err as Error).message })
}
})
// -------------------------------------------------------------
// ▶ Zeit bearbeiten
// -------------------------------------------------------------
server.put("/staff/time/:id", async (req, reply) => {
try {
const { id } = req.params as any
const updateData = {
// @ts-ignore
...req.body,
updated_at: new Date()
}
const [updated] = await server.db
.update(stafftimeentries)
.set(updateData)
.where(eq(stafftimeentries.id, id))
.returning()
return updated
} catch (err) {
return reply.code(400).send({ error: (err as Error).message })
}
})
// -------------------------------------------------------------
// ▶ Zeit löschen
server.delete<{ Params: { id: string } }>(
'/staff/time/:id',
async (req, reply) => {
const { id } = req.params
const { error } = await server.supabase
.from('staff_time_entries')
.delete()
.eq('id', id)
// -------------------------------------------------------------
server.delete("/staff/time/:id", async (req, reply) => {
try {
const { id } = req.params as any
if (error) return reply.code(400).send({ error: error.message })
return reply.send({ success: true })
await server.db
.delete(stafftimeentries)
.where(eq(stafftimeentries.id, id))
return { success: true }
} catch (err) {
return reply.code(400).send({ error: (err as Error).message })
}
)
})
}