Skip to content
Merged

fixes #201

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions apps/next-frontend/app/api/debug/invite-codes/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { db } from '@ticketeate/db';

export const dynamic = 'force-dynamic';

export async function GET(request: Request) {
try {
// Verificar que la tabla invite_codes existe
const inviteCodesCount = await db.invite_codes.count();
const colaboradoresCount = await db.colaborador_eventos.count();

// Obtener los primeros 5 códigos de invitación
const inviteCodes = await db.invite_codes.findMany({
take: 5,
include: {
eventos: {
select: {
eventoid: true,
nombre: true,
},
},
},
});

return Response.json({
status: 'ok',
inviteCodesCount,
colaboradoresCount,
recentInviteCodes: inviteCodes,
});
} catch (error) {
console.error('Error in debug endpoint:', error);
return Response.json({ error: 'Error in debug endpoint' }, { status: 500 });
}
}
99 changes: 99 additions & 0 deletions apps/next-frontend/app/api/invite-codes/use/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { auth } from '@/lib/auth';
import { db } from '@ticketeate/db';

export const dynamic = 'force-dynamic';

interface UseInviteCodeResponse {
success: boolean;
message: string;
eventoid?: string;
colaborador_evento_id?: string;
error?: string;
}

export async function POST(request: Request): Promise<Response> {
try {
// Obtener la sesión del usuario
const session = await auth.api.getSession({
headers: request.headers,
});

if (!session || !session.user) {
return Response.json({ error: 'Usuario no autenticado' }, { status: 401 });
}

const { codigo } = await request.json();

if (!codigo || typeof codigo !== 'string') {
return Response.json({ error: 'Código de invitación requerido' }, { status: 400 });
}

const codigoTrimmed = codigo.trim().toUpperCase();

// Buscar el código en la base de datos
const inviteCode = await db.invite_codes.findFirst({
where: {
codigo: codigoTrimmed,
estado: 'ACTIVO',
fecha_expiracion: {
gt: new Date(),
},
},
});

if (!inviteCode) {
return Response.json({ error: 'Código de invitación no válido o expirado' }, { status: 401 });
}

// Verificar que no ha excedido el máximo de usos
if (inviteCode.usos_totales >= inviteCode.usos_max) {
return Response.json(
{ error: 'Código de invitación ya ha alcanzado el máximo de usos' },
{ status: 401 },
);
}

// Verificar si el usuario ya es colaborador de este evento
const existingColaborador = await db.colaborador_eventos.findFirst({
where: {
eventoid: inviteCode.eventoid,
usuarioid: session.user.id,
},
});

if (existingColaborador) {
return Response.json({ error: 'Ya eres colaborador de este evento' }, { status: 400 });
}

// Crear el registro de colaborador_eventos
const colaborador = await db.colaborador_eventos.create({
data: {
eventoid: inviteCode.eventoid,
usuarioid: session.user.id,
invite_code_used: inviteCode.codigoid,
},
});

// Incrementar el contador de usos del código
await db.invite_codes.update({
where: {
codigoid: inviteCode.codigoid,
},
data: {
usos_totales: {
increment: 1,
},
},
});

return Response.json({
success: true,
message: 'Te has registrado como colaborador correctamente',
eventoid: inviteCode.eventoid,
colaborador_evento_id: colaborador.colaborador_evento_id,
} as UseInviteCodeResponse);
} catch (error) {
console.error('Error using invite code:', error);
return Response.json({ error: 'Error al usar código de invitación' }, { status: 500 });
}
}
68 changes: 68 additions & 0 deletions apps/next-frontend/app/api/invite-codes/validate/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { auth } from '@/lib/auth';
import { db } from '@ticketeate/db';

export const dynamic = 'force-dynamic';

interface ValidateInviteCodeResponse {
valid: boolean;
eventoid?: string;
evento?: {
eventoid: string;
nombre: string;
descripcion: string;
fecha_inicio: string;
};
error?: string;
}

export async function POST(request: Request): Promise<Response> {
try {
const { codigo } = await request.json();

if (!codigo || typeof codigo !== 'string') {
return Response.json({ error: 'Código de invitación requerido' }, { status: 400 });
}

// Buscar el código en la base de datos
const inviteCode = await db.invite_codes.findFirst({
where: {
codigo: codigo.trim().toUpperCase(),
estado: 'ACTIVO',
fecha_expiracion: {
gt: new Date(), // Mayor que la fecha actual
},
},
include: {
eventos: {
select: {
eventoid: true,
nombre: true,
descripcion: true,
fecha_inicio: true,
},
},
},
});

if (!inviteCode) {
return Response.json({ error: 'Código de invitación no válido o expirado' }, { status: 401 });
}

// Verificar que no ha excedido el máximo de usos
if (inviteCode.usos_totales >= inviteCode.usos_max) {
return Response.json(
{ error: 'Código de invitación ya ha alcanzado el máximo de usos' },
{ status: 401 },
);
}

return Response.json({
valid: true,
eventoid: inviteCode.eventoid,
evento: inviteCode.eventos,
} as ValidateInviteCodeResponse);
} catch (error) {
console.error('Error validating invite code:', error);
return Response.json({ error: 'Error validando código de invitación' }, { status: 500 });
}
}
27 changes: 23 additions & 4 deletions apps/next-frontend/app/api/mercadopago/create-preference/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,19 @@ export async function POST(request: NextRequest) {
},
auto_return: 'approved',
metadata: {
...metadata,
// Información del evento
event_id: metadata?.event_id,
event_titulo: metadata?.event_titulo,
// Información del comprador
buyer_id: metadata?.buyer_id,
buyer_email: metadata?.buyer_email,
buyer_nombre: metadata?.buyer_nombre,
// Información del pedido
cantidad: metadata?.cantidad,
sector: metadata?.sector,
precio_unitario: metadata?.precio_unitario,
transaction_id: metadata?.transaction_id,
// Información del vendedor/organizador
seller_id: seller.id,
seller_mp_user_id: seller.mercado_pago_user_id,
marketplace_fee: marketplaceFee,
Expand Down Expand Up @@ -190,10 +202,17 @@ export async function POST(request: NextRequest) {
marketplace_fee: marketplaceFee,
status: 'pending',
metadata: {
...metadata,
event_id: metadata?.event_id,
event_titulo: metadata?.event_titulo,
buyer_id: metadata?.buyer_id,
buyer_email: metadata?.buyer_email,
buyer_nombre: metadata?.buyer_nombre,
cantidad: metadata?.cantidad,
sector: metadata?.sector,
precio_unitario: metadata?.precio_unitario,
transaction_id: metadata?.transaction_id,
seller_id: seller.id,
buyer_id: session.user.id,
event_id: eventId,
seller_mp_user_id: seller.mercado_pago_user_id,
marketplace_fee: marketplaceFee,
},
},
Expand Down
Loading
Loading