Add repair notes journal with running feed, visibility, and status tagging
New repair_note table for timestamped journal entries on tickets. Each note captures author, content, visibility (internal or customer-facing), and the ticket status at time of writing. Notes display as a running feed on the ticket detail page with newest first. Internal notes have a lock icon, customer-visible notes highlighted in blue. Supports add and delete with appropriate permission gating.
This commit is contained in:
@@ -9,10 +9,11 @@ import {
|
||||
RepairBatchCreateSchema,
|
||||
RepairBatchUpdateSchema,
|
||||
RepairBatchStatusUpdateSchema,
|
||||
RepairNoteCreateSchema,
|
||||
RepairServiceTemplateCreateSchema,
|
||||
RepairServiceTemplateUpdateSchema,
|
||||
} from '@forte/shared/schemas'
|
||||
import { RepairTicketService, RepairLineItemService, RepairBatchService, RepairServiceTemplateService } from '../../services/repair.service.js'
|
||||
import { RepairTicketService, RepairLineItemService, RepairBatchService, RepairNoteService, RepairServiceTemplateService } from '../../services/repair.service.js'
|
||||
|
||||
export const repairRoutes: FastifyPluginAsync = async (app) => {
|
||||
// --- Repair Tickets ---
|
||||
@@ -187,6 +188,39 @@ export const repairRoutes: FastifyPluginAsync = async (app) => {
|
||||
return reply.send(result)
|
||||
})
|
||||
|
||||
// --- Repair Notes ---
|
||||
|
||||
app.post('/repair-tickets/:ticketId/notes', { preHandler: [app.authenticate, app.requirePermission('repairs.edit')] }, async (request, reply) => {
|
||||
const { ticketId } = request.params as { ticketId: string }
|
||||
const parsed = RepairNoteCreateSchema.safeParse(request.body)
|
||||
if (!parsed.success) {
|
||||
return reply.status(400).send({ error: { message: 'Validation failed', details: parsed.error.flatten(), statusCode: 400 } })
|
||||
}
|
||||
const ticket = await RepairTicketService.getById(app.db, request.companyId, ticketId)
|
||||
if (!ticket) return reply.status(404).send({ error: { message: 'Repair ticket not found', statusCode: 404 } })
|
||||
|
||||
// Look up author name from users table
|
||||
const { users } = await import('../../db/schema/users.js')
|
||||
const { eq } = await import('drizzle-orm')
|
||||
const [author] = await app.db.select({ firstName: users.firstName, lastName: users.lastName }).from(users).where(eq(users.id, request.user.id)).limit(1)
|
||||
const authorName = author ? `${author.firstName} ${author.lastName}` : 'Unknown'
|
||||
const note = await RepairNoteService.create(app.db, ticketId, request.user.id, authorName, ticket.status, parsed.data)
|
||||
return reply.status(201).send(note)
|
||||
})
|
||||
|
||||
app.get('/repair-tickets/:ticketId/notes', { preHandler: [app.authenticate, app.requirePermission('repairs.view')] }, async (request, reply) => {
|
||||
const { ticketId } = request.params as { ticketId: string }
|
||||
const notes = await RepairNoteService.listByTicket(app.db, ticketId)
|
||||
return reply.send({ data: notes })
|
||||
})
|
||||
|
||||
app.delete('/repair-notes/:id', { preHandler: [app.authenticate, app.requirePermission('repairs.admin')] }, async (request, reply) => {
|
||||
const { id } = request.params as { id: string }
|
||||
const note = await RepairNoteService.delete(app.db, id)
|
||||
if (!note) return reply.status(404).send({ error: { message: 'Note not found', statusCode: 404 } })
|
||||
return reply.send(note)
|
||||
})
|
||||
|
||||
// --- Repair Service Templates ---
|
||||
|
||||
app.post('/repair-service-templates', { preHandler: [app.authenticate, app.requirePermission('repairs.admin')] }, async (request, reply) => {
|
||||
|
||||
Reference in New Issue
Block a user