implementado el manejo de errores correcto de prisma
Some checks failed
build-and-deploy / filter (push) Successful in 2s
Sync to GitHub / sync (push) Failing after 1s
build-and-deploy / build (push) Successful in 9s
build-and-deploy / deploy (push) Successful in 14s

This commit is contained in:
2025-05-30 12:44:51 -06:00
parent 4066217862
commit 97b879433d
4 changed files with 162 additions and 134 deletions

View File

@@ -8,8 +8,8 @@ router.get('/', async (req, res) => {
try { try {
const asistencias = await prisma.asistencia.findMany(); const asistencias = await prisma.asistencia.findMany();
res.json(asistencias); res.json(asistencias);
} catch (error) { } catch (e) {
console.error(error); console.error(e);
res.status(500).json({ message: 'Error al obtener asistencias.' }); res.status(500).json({ message: 'Error al obtener asistencias.' });
} }
}); });
@@ -26,13 +26,13 @@ router.get('/:id', async (req, res) => {
} else { } else {
res.status(404).json({ message: 'Asistencia no encontrada.' }); res.status(404).json({ message: 'Asistencia no encontrada.' });
} }
} catch (error) { } catch (e) {
console.error(error); console.error(e);
res.status(500).json({ message: 'Error al obtener asistencia.' }); res.status(500).json({ message: 'Error al obtener asistencia.' });
} }
}); });
// POST crear asistencia // POST crear asistencia
router.post('/', async (req, res) => { router.post('/', async (req, res) => {
const { const {
empleado_id, empleado_id,
@@ -45,99 +45,107 @@ router.post('/', async (req, res) => {
creador_id, creador_id,
modificado_id, modificado_id,
anulador_id, anulador_id,
} = req.body } = req.body;
if (!empleado_id) if (!empleado_id)
return res.status(400).json({ message: 'El campo empleado_id es obligatorio.' }) return res.status(400).json({ message: 'El campo empleado_id es obligatorio.' });
try { try {
const nuevaAsistencia = await prisma.asistencia.create({ const nuevaAsistencia = await prisma.asistencia.create({
data: { data: {
empleado_id: BigInt(empleado_id), // FK a Cliente.id empleado_id: BigInt(empleado_id),
entrada: entrada ? new Date(entrada) : null, entrada: entrada ? new Date(entrada) : null,
salida: salida ? new Date(salida) : null, salida: salida ? new Date(salida) : null,
historial, // JSON historial,
observacion, observacion,
estado, estado,
fecha_anulado: fecha_anulado ? new Date(fecha_anulado) : null, fecha_anulado: fecha_anulado ? new Date(fecha_anulado) : null,
creador_id, creador_id,
modificado_id, modificado_id,
anulador_id, anulador_id,
}, },
}) });
res.status(201).json(nuevaAsistencia);
res.status(201).json(nuevaAsistencia) } catch (e) {
} catch (e){ if (e instanceof Prisma.PrismaClientKnownRequestError) {
if (e.code === 'P2003' && e.meta?.field_name?.includes('empleado_id')) {
// ⚠️ captura FK error: Asistencia_empleado_id_fkey return res.status(400).json({ message: 'El empleado_id proporcionado no existe.' });
if(e instanceof Prisma.PrismaClientKnownRequestError ) {
if( e.code === 'P2003') {
return res.status(400).json({ message: 'El empleado_id proporcionado no existe.' })
} }
} }
console.error(e) console.error(e);
res.status(500).json({ message: 'Error al crear asistencia.' }) res.status(500).json({ message: 'Error al crear asistencia.' });
} }
}) });
// PUT actualizar asistencia
// PUT update asistencia by ID
router.put('/:id', async (req, res) => { router.put('/:id', async (req, res) => {
const { id } = req.params; const { id } = req.params;
const { empleado_id, entrada, salida, historial, observacion, estado, fecha_anulado, modificado_id, anulador_id } = req.body; const {
empleado_id,
entrada,
salida,
historial,
observacion,
estado,
fecha_anulado,
modificado_id,
anulador_id,
} = req.body;
try { try {
const updateData = { const updateData = {
entrada: entrada ? new Date(entrada) : undefined, entrada: entrada ? new Date(entrada) : undefined,
salida: salida ? new Date(salida) : undefined, salida: salida ? new Date(salida) : undefined,
historial, historial,
observacion, observacion,
estado, estado,
fecha_anulado: fecha_anulado ? new Date(fecha_anulado) : undefined, fecha_anulado: fecha_anulado ? new Date(fecha_anulado) : undefined,
modificado_id, // Should ideally be taken from authenticated user modificado_id,
anulador_id anulador_id,
}; };
// If empleado_id is provided, include it in updateData.
// Be cautious: changing empleado_id might not be a typical operation for an existing attendance record.
if (empleado_id !== undefined) { if (empleado_id !== undefined) {
updateData.empleado_id = parseInt(empleado_id); updateData.empleado_id = BigInt(empleado_id);
} }
const asistenciaActualizada = await prisma.asistencia.update({ const asistenciaActualizada = await prisma.asistencia.update({
where: { id: parseInt(id) }, where: { id: parseInt(id) },
data: updateData, data: updateData,
}); });
res.json(asistenciaActualizada); res.json(asistenciaActualizada);
} catch (error) { } catch (e) {
console.error(error); if (e instanceof Prisma.PrismaClientKnownRequestError) {
if (error.code === 'P2025') { // Record to update not found if (e.code === 'P2025') {
return res.status(404).json({ message: 'Asistencia no encontrada para actualizar.' }); return res.status(404).json({ message: 'Asistencia no encontrada para actualizar.' });
} }
if (error.code === 'P2003') { // Foreign key constraint failed if (e.code === 'P2003' && e.meta?.field_name?.includes('empleado_id')) {
if (error.meta?.field_name?.includes('empleado_id')) { return res.status(400).json({ message: 'El empleado_id proporcionado no existe.' });
return res.status(400).json({ message: 'El empleado_id proporcionado no existe.' }); }
}
} }
console.error(e);
res.status(500).json({ message: 'Error al actualizar asistencia.' }); res.status(500).json({ message: 'Error al actualizar asistencia.' });
} }
}); });
// DELETE asistencia by ID // DELETE asistencia
router.delete('/:id', async (req, res) => { router.delete('/:id', async (req, res) => {
const { id } = req.params; const { id } = req.params;
try { try {
await prisma.asistencia.delete({ await prisma.asistencia.delete({
where: { id: parseInt(id) }, where: { id: parseInt(id) },
}); });
res.status(204).send(); // No content res.status(204).send();
} catch (error) { } catch (e) {
console.error(error); if (e instanceof Prisma.PrismaClientKnownRequestError) {
if (error.code === 'P2025') { // Record to delete not found if (e.code === 'P2025') {
return res.status(404).json({ message: 'Asistencia no encontrada para eliminar.' }); return res.status(404).json({ message: 'Asistencia no encontrada para eliminar.' });
}
} }
console.error(e);
res.status(500).json({ message: 'Error al eliminar asistencia.' }); res.status(500).json({ message: 'Error al eliminar asistencia.' });
} }
}); });

View File

@@ -1,10 +1,9 @@
import express from 'express' import express from 'express'
import { PrismaClient } from '../../prisma/generated/client/index.js' import { PrismaClient, Prisma } from '../../prisma/generated/client/index.js'
const router = express.Router() const router = express.Router()
const prisma = new PrismaClient() const prisma = new PrismaClient()
// ⚙️ helper: evita el crash al serializar BigInt
const fixBigInt = (data) => const fixBigInt = (data) =>
JSON.parse(JSON.stringify(data, (_, v) => (typeof v === 'bigint' ? v.toString() : v))) JSON.parse(JSON.stringify(data, (_, v) => (typeof v === 'bigint' ? v.toString() : v)))
@@ -59,9 +58,13 @@ router.post('/', async (req, res) => {
}) })
res.status(201).json(fixBigInt(nuevo)) res.status(201).json(fixBigInt(nuevo))
} catch (e) { } catch (e) {
if (e instanceof Prisma.PrismaClientKnownRequestError) {
if (e.code === 'P2002' && e.meta?.target?.includes('cedula')) {
return res.status(400).json({ message: 'Ya existe un cliente con esa cédula.' })
}
}
console.error(e) console.error(e)
if (e.code === 'P2002' && e.meta?.target?.includes('cedula'))
return res.status(400).json({ message: 'Ya existe un cliente con esa cédula.' })
res.status(500).json({ message: 'Error al crear empleado.' }) res.status(500).json({ message: 'Error al crear empleado.' })
} }
}) })
@@ -97,11 +100,16 @@ router.put('/:id', async (req, res) => {
}) })
res.json(fixBigInt(actualizado)) res.json(fixBigInt(actualizado))
} catch (e) { } catch (e) {
if (e instanceof Prisma.PrismaClientKnownRequestError) {
if (e.code === 'P2002' && e.meta?.target?.includes('cedula')) {
return res.status(400).json({ message: 'Ya existe un cliente con esa cédula.' })
}
if (e.code === 'P2025') {
return res.status(404).json({ message: 'Empleado no encontrado para actualizar.' })
}
}
console.error(e) console.error(e)
if (e.code === 'P2002' && e.meta?.target?.includes('cedula'))
return res.status(400).json({ message: 'Ya existe un cliente con esa cédula.' })
if (e.code === 'P2025')
return res.status(404).json({ message: 'Empleado no encontrado para actualizar.' })
res.status(500).json({ message: 'Error al actualizar empleado.' }) res.status(500).json({ message: 'Error al actualizar empleado.' })
} }
}) })
@@ -116,9 +124,13 @@ router.delete('/:id', async (req, res) => {
await prisma.cliente.delete({ where: { id } }) await prisma.cliente.delete({ where: { id } })
res.status(204).send() res.status(204).send()
} catch (e) { } catch (e) {
if (e instanceof Prisma.PrismaClientKnownRequestError) {
if (e.code === 'P2025') {
return res.status(404).json({ message: 'Empleado no encontrado para eliminar.' })
}
}
console.error(e) console.error(e)
if (e.code === 'P2025')
return res.status(404).json({ message: 'Empleado no encontrado para eliminar.' })
res.status(500).json({ message: 'Error al eliminar empleado.' }) res.status(500).json({ message: 'Error al eliminar empleado.' })
} }
}) })

View File

@@ -1,6 +1,6 @@
import express from 'express'; import express from 'express';
const router = express.Router(); const router = express.Router();
import { PrismaClient } from '../../prisma/generated/client/index.js'; import { PrismaClient, Prisma } from '../../prisma/generated/client/index.js';
const prisma = new PrismaClient(); const prisma = new PrismaClient();
// GET all planillas // GET all planillas
@@ -8,8 +8,8 @@ router.get('/', async (req, res) => {
try { try {
const planillas = await prisma.planilla.findMany(); const planillas = await prisma.planilla.findMany();
res.json(planillas); res.json(planillas);
} catch (error) { } catch (e) {
console.error(error); console.error(e);
res.status(500).json({ message: 'Error al obtener planillas.' }); res.status(500).json({ message: 'Error al obtener planillas.' });
} }
}); });
@@ -26,8 +26,8 @@ router.get('/:id', async (req, res) => {
} else { } else {
res.status(404).json({ message: 'Planilla no encontrada.' }); res.status(404).json({ message: 'Planilla no encontrada.' });
} }
} catch (error) { } catch (e) {
console.error(error); console.error(e);
res.status(500).json({ message: 'Error al obtener planilla.' }); res.status(500).json({ message: 'Error al obtener planilla.' });
} }
}); });
@@ -42,37 +42,38 @@ router.post('/', async (req, res) => {
total, total,
estado, estado,
fecha_anulado, fecha_anulado,
creador_id, // Should ideally be from authenticated user creador_id,
anulador_id, anulador_id,
} = req.body; } = req.body;
try { if (!empleado_id || !fecha_desde || !fecha_hasta || !titulo) {
// Basic validation return res.status(400).json({
if (!empleado_id || !fecha_desde || !fecha_hasta || !titulo) { message: 'Los campos empleado_id, fecha_desde, fecha_hasta y titulo son obligatorios.',
return res.status(400).json({ message: 'Los campos empleado_id, fecha_desde, fecha_hasta y titulo son obligatorios.' }); });
} }
try {
const nuevaPlanilla = await prisma.planilla.create({ const nuevaPlanilla = await prisma.planilla.create({
data: { data: {
empleado_id: parseInt(empleado_id), empleado_id: parseInt(empleado_id),
fecha_desde: new Date(fecha_desde), fecha_desde: new Date(fecha_desde),
fecha_hasta: new Date(fecha_hasta), fecha_hasta: new Date(fecha_hasta),
titulo, titulo,
total: total ? parseFloat(total) : null, // Prisma expects Decimal to be passed as number or string total: total ? parseFloat(total) : null,
estado: estado || 'pagado', // Default to 'pagado' if not provided estado: estado || 'pagado',
fecha_anulado: fecha_anulado ? new Date(fecha_anulado) : null, fecha_anulado: fecha_anulado ? new Date(fecha_anulado) : null,
creador_id, creador_id,
anulador_id, anulador_id,
}, },
}); });
res.status(201).json(nuevaPlanilla); res.status(201).json(nuevaPlanilla);
} catch (error) { } catch (e) {
console.error(error); if (e instanceof Prisma.PrismaClientKnownRequestError) {
if (error.code === 'P2003') { // Foreign key constraint failed if (e.code === 'P2003' && e.meta?.field_name?.includes('empleado_id')) {
if (error.meta?.field_name?.includes('empleado_id')) {
return res.status(400).json({ message: 'El empleado_id proporcionado no existe.' }); return res.status(400).json({ message: 'El empleado_id proporcionado no existe.' });
} }
} }
console.error(e);
res.status(500).json({ message: 'Error al crear planilla.' }); res.status(500).json({ message: 'Error al crear planilla.' });
} }
}); });
@@ -101,23 +102,22 @@ router.put('/:id', async (req, res) => {
if (estado !== undefined) updateData.estado = estado; if (estado !== undefined) updateData.estado = estado;
if (fecha_anulado !== undefined) updateData.fecha_anulado = fecha_anulado ? new Date(fecha_anulado) : null; if (fecha_anulado !== undefined) updateData.fecha_anulado = fecha_anulado ? new Date(fecha_anulado) : null;
if (anulador_id !== undefined) updateData.anulador_id = anulador_id; if (anulador_id !== undefined) updateData.anulador_id = anulador_id;
// creador_id is typically not updated.
const planillaActualizada = await prisma.planilla.update({ const planillaActualizada = await prisma.planilla.update({
where: { id: parseInt(id) }, where: { id: parseInt(id) },
data: updateData, data: updateData,
}); });
res.json(planillaActualizada); res.json(planillaActualizada);
} catch (error) { } catch (e) {
console.error(error); if (e instanceof Prisma.PrismaClientKnownRequestError) {
if (error.code === 'P2025') { // Record to update not found if (e.code === 'P2025') {
return res.status(404).json({ message: 'Planilla no encontrada para actualizar.' }); return res.status(404).json({ message: 'Planilla no encontrada para actualizar.' });
} }
if (error.code === 'P2003') { // Foreign key constraint failed if (e.code === 'P2003' && e.meta?.field_name?.includes('empleado_id')) {
if (error.meta?.field_name?.includes('empleado_id')) {
return res.status(400).json({ message: 'El empleado_id proporcionado no existe.' }); return res.status(400).json({ message: 'El empleado_id proporcionado no existe.' });
} }
} }
console.error(e);
res.status(500).json({ message: 'Error al actualizar planilla.' }); res.status(500).json({ message: 'Error al actualizar planilla.' });
} }
}); });
@@ -129,12 +129,14 @@ router.delete('/:id', async (req, res) => {
await prisma.planilla.delete({ await prisma.planilla.delete({
where: { id: parseInt(id) }, where: { id: parseInt(id) },
}); });
res.status(204).send(); // No content res.status(204).send();
} catch (error) { } catch (e) {
console.error(error); if (e instanceof Prisma.PrismaClientKnownRequestError) {
if (error.code === 'P2025') { // Record to delete not found if (e.code === 'P2025') {
return res.status(404).json({ message: 'Planilla no encontrada para eliminar.' }); return res.status(404).json({ message: 'Planilla no encontrada para eliminar.' });
}
} }
console.error(e);
res.status(500).json({ message: 'Error al eliminar planilla.' }); res.status(500).json({ message: 'Error al eliminar planilla.' });
} }
}); });

View File

@@ -1,6 +1,6 @@
import express from 'express'; import express from 'express';
const router = express.Router(); const router = express.Router();
import { PrismaClient } from '../../prisma/generated/client/index.js'; import { PrismaClient, Prisma } from '../../prisma/generated/client/index.js';
const prisma = new PrismaClient(); const prisma = new PrismaClient();
// GET all tareas // GET all tareas
@@ -8,9 +8,9 @@ router.get('/', async (req, res) => {
try { try {
const tareas = await prisma.tareaRealizada.findMany(); const tareas = await prisma.tareaRealizada.findMany();
res.json(tareas); res.json(tareas);
} catch (error) { } catch (e) {
console.error(error); console.error(e);
res.status(500).json({ message: 'Error al obtener tareas.' }); res.status(500).json({ message: 'Error al obtener tareas.' });
} }
}); });
@@ -26,8 +26,8 @@ router.get('/:id', async (req, res) => {
} else { } else {
res.status(404).json({ message: 'Tarea no encontrada.' }); res.status(404).json({ message: 'Tarea no encontrada.' });
} }
} catch (error) { } catch (e) {
console.error(error); console.error(e);
res.status(500).json({ message: 'Error al obtener tarea.' }); res.status(500).json({ message: 'Error al obtener tarea.' });
} }
}); });
@@ -44,42 +44,45 @@ router.post('/', async (req, res) => {
fecha, fecha,
tipo, tipo,
fecha_anulado, fecha_anulado,
creador_id, // Should ideally be from authenticated user creador_id,
anulador_id, anulador_id,
} = req.body; } = req.body;
try { if (!empleado_id || !titulo || !fecha) {
// Basic validation return res.status(400).json({
if (!empleado_id || !titulo || !fecha) { message: 'Los campos empleado_id, titulo y fecha son obligatorios.',
return res.status(400).json({ message: 'Los campos empleado_id, titulo y fecha son obligatorios.' }); });
} }
try {
const nuevaTarea = await prisma.tareaRealizada.create({ const nuevaTarea = await prisma.tareaRealizada.create({
data: { data: {
empleado_id: parseInt(empleado_id), empleado_id: parseInt(empleado_id),
planilla_id: planilla_id ? parseInt(planilla_id) : null, planilla_id: planilla_id ? parseInt(planilla_id) : null,
titulo, titulo,
precio: precio ? parseFloat(precio) : null, precio: precio ? parseFloat(precio) : null,
estado: estado || 'pendiente', // Default to 'pendiente' if not provided estado: estado || 'pendiente',
observacion, observacion,
fecha: new Date(fecha), fecha: new Date(fecha),
tipo: tipo || '', // Default to empty string if not provided tipo: tipo || '',
fecha_anulado: fecha_anulado ? new Date(fecha_anulado) : null, fecha_anulado: fecha_anulado ? new Date(fecha_anulado) : null,
creador_id, creador_id,
anulador_id, anulador_id,
}, },
}); });
res.status(201).json(nuevaTarea); res.status(201).json(nuevaTarea);
} catch (error) { } catch (e) {
console.error(error); if (e instanceof Prisma.PrismaClientKnownRequestError) {
if (error.code === 'P2003') { // Foreign key constraint failed if (e.code === 'P2003') {
if (error.meta?.field_name?.includes('empleado_id')) { if (e.meta?.field_name?.includes('empleado_id')) {
return res.status(400).json({ message: 'El empleado_id proporcionado no existe.' }); return res.status(400).json({ message: 'El empleado_id proporcionado no existe.' });
} }
if (error.meta?.field_name?.includes('planilla_id')) { if (e.meta?.field_name?.includes('planilla_id')) {
return res.status(400).json({ message: 'El planilla_id proporcionado no existe.' }); return res.status(400).json({ message: 'El planilla_id proporcionado no existe.' });
}
} }
} }
console.error(e);
res.status(500).json({ message: 'Error al crear tarea.' }); res.status(500).json({ message: 'Error al crear tarea.' });
} }
}); });
@@ -112,26 +115,27 @@ router.put('/:id', async (req, res) => {
if (tipo !== undefined) updateData.tipo = tipo; if (tipo !== undefined) updateData.tipo = tipo;
if (fecha_anulado !== undefined) updateData.fecha_anulado = fecha_anulado ? new Date(fecha_anulado) : null; if (fecha_anulado !== undefined) updateData.fecha_anulado = fecha_anulado ? new Date(fecha_anulado) : null;
if (anulador_id !== undefined) updateData.anulador_id = anulador_id; if (anulador_id !== undefined) updateData.anulador_id = anulador_id;
// creador_id is typically not updated.
const tareaActualizada = await prisma.tareaRealizada.update({ const tareaActualizada = await prisma.tareaRealizada.update({
where: { id: parseInt(id) }, where: { id: parseInt(id) },
data: updateData, data: updateData,
}); });
res.json(tareaActualizada); res.json(tareaActualizada);
} catch (error) { } catch (e) {
console.error(error); if (e instanceof Prisma.PrismaClientKnownRequestError) {
if (error.code === 'P2025') { // Record to update not found if (e.code === 'P2025') {
return res.status(404).json({ message: 'Tarea no encontrada para actualizar.' }); return res.status(404).json({ message: 'Tarea no encontrada para actualizar.' });
}
if (error.code === 'P2003') { // Foreign key constraint failed
if (error.meta?.field_name?.includes('empleado_id')) {
return res.status(400).json({ message: 'El empleado_id proporcionado no existe.' });
} }
if (error.meta?.field_name?.includes('planilla_id')) { if (e.code === 'P2003') {
return res.status(400).json({ message: 'El planilla_id proporcionado no existe.' }); if (e.meta?.field_name?.includes('empleado_id')) {
return res.status(400).json({ message: 'El empleado_id proporcionado no existe.' });
}
if (e.meta?.field_name?.includes('planilla_id')) {
return res.status(400).json({ message: 'El planilla_id proporcionado no existe.' });
}
} }
} }
console.error(e);
res.status(500).json({ message: 'Error al actualizar tarea.' }); res.status(500).json({ message: 'Error al actualizar tarea.' });
} }
}); });
@@ -143,12 +147,14 @@ router.delete('/:id', async (req, res) => {
await prisma.tareaRealizada.delete({ await prisma.tareaRealizada.delete({
where: { id: parseInt(id) }, where: { id: parseInt(id) },
}); });
res.status(204).send(); // No content res.status(204).send();
} catch (error) { } catch (e) {
console.error(error); if (e instanceof Prisma.PrismaClientKnownRequestError) {
if (error.code === 'P2025') { // Record to delete not found if (e.code === 'P2025') {
return res.status(404).json({ message: 'Tarea no encontrada para eliminar.' }); return res.status(404).json({ message: 'Tarea no encontrada para eliminar.' });
}
} }
console.error(e);
res.status(500).json({ message: 'Error al eliminar tarea.' }); res.status(500).json({ message: 'Error al eliminar tarea.' });
} }
}); });