Se corrigió hardcode de id de template y se permite recibir body para el downloadReport
This commit is contained in:
@@ -18,6 +18,7 @@ const ActionSchema = z.object({
|
||||
const DownloadReportSchema = z.object({
|
||||
action: z.literal("downloadReport"),
|
||||
plan_estudio_id: z.string().min(1),
|
||||
body: z.record(z.unknown()),
|
||||
});
|
||||
|
||||
type DownloadReportInput = z.infer<typeof DownloadReportSchema>;
|
||||
@@ -29,10 +30,10 @@ function getAuthHeader(req: Request): string | null {
|
||||
async function loadPlanDatos(
|
||||
supabase: ReturnType<typeof createClient<Database>>,
|
||||
planEstudioId: string,
|
||||
): Promise<Json> {
|
||||
): Promise<{ datos: Json; estructura_id: string }> {
|
||||
const { data, error } = await supabase
|
||||
.from("planes_estudio")
|
||||
.select("datos")
|
||||
.select("datos, estructura_id")
|
||||
.eq("id", planEstudioId)
|
||||
.maybeSingle();
|
||||
|
||||
@@ -52,7 +53,48 @@ async function loadPlanDatos(
|
||||
{ plan_estudio_id: planEstudioId },
|
||||
);
|
||||
}
|
||||
return data.datos;
|
||||
|
||||
return {
|
||||
datos: data.datos,
|
||||
estructura_id: data.estructura_id,
|
||||
};
|
||||
}
|
||||
|
||||
async function loadTemplateIdForEstructura(
|
||||
supabase: ReturnType<typeof createClient<Database>>,
|
||||
estructuraId: string,
|
||||
): Promise<string> {
|
||||
const { data, error } = await supabase
|
||||
.from("estructuras_plan")
|
||||
.select("template_id")
|
||||
.eq("id", estructuraId)
|
||||
.maybeSingle();
|
||||
|
||||
if (error) {
|
||||
throw new HttpError(
|
||||
500,
|
||||
"Error consultando la estructura del plan.",
|
||||
"DB_ERROR",
|
||||
{ message: error.message, details: error.details, hint: error.hint },
|
||||
);
|
||||
}
|
||||
if (!data) {
|
||||
throw new HttpError(
|
||||
404,
|
||||
"Estructura del plan no encontrada.",
|
||||
"NOT_FOUND",
|
||||
{ estructura_id: estructuraId },
|
||||
);
|
||||
}
|
||||
if (!data.template_id) {
|
||||
throw new HttpError(
|
||||
409,
|
||||
"La estructura del plan no tiene template_id configurado.",
|
||||
"MISSING_TEMPLATE_ID",
|
||||
{ estructura_id: estructuraId },
|
||||
);
|
||||
}
|
||||
return data.template_id;
|
||||
}
|
||||
|
||||
Deno.serve(async (req: Request): Promise<Response> => {
|
||||
@@ -110,10 +152,9 @@ Deno.serve(async (req: Request): Promise<Response> => {
|
||||
}
|
||||
|
||||
const CARBONE_API_TOKEN = Deno.env.get("CARBONE_API_TOKEN");
|
||||
const CARBONE_TEMPLATE_ID = Deno.env.get("CARBONE_TEMPLATE_ID");
|
||||
const CARBONE_BASE_URL = Deno.env.get("CARBONE_BASE_URL") ||
|
||||
"https://carbone.lci.ulsa.mx";
|
||||
if (!CARBONE_API_TOKEN || !CARBONE_TEMPLATE_ID) {
|
||||
if (!CARBONE_API_TOKEN) {
|
||||
throw new HttpError(
|
||||
500,
|
||||
"Configuración del servidor incompleta.",
|
||||
@@ -121,7 +162,6 @@ Deno.serve(async (req: Request): Promise<Response> => {
|
||||
{
|
||||
missing: [
|
||||
!CARBONE_API_TOKEN ? "CARBONE_API_TOKEN" : null,
|
||||
!CARBONE_TEMPLATE_ID ? "CARBONE_TEMPLATE_ID" : null,
|
||||
].filter(Boolean),
|
||||
},
|
||||
);
|
||||
@@ -140,12 +180,22 @@ Deno.serve(async (req: Request): Promise<Response> => {
|
||||
bodyUnknown,
|
||||
);
|
||||
|
||||
const datos = await loadPlanDatos(supabase, input.plan_estudio_id);
|
||||
const { datos, estructura_id } = await loadPlanDatos(
|
||||
supabase,
|
||||
input.plan_estudio_id,
|
||||
);
|
||||
const templateId = await loadTemplateIdForEstructura(
|
||||
supabase,
|
||||
estructura_id,
|
||||
);
|
||||
const carbone = new CarboneClient(CARBONE_BASE_URL, CARBONE_API_TOKEN);
|
||||
|
||||
const { data: _ignoredData, ...extraBody } = input.body;
|
||||
|
||||
console.log("body:", extraBody);
|
||||
const result = await carbone.render(
|
||||
CARBONE_TEMPLATE_ID,
|
||||
{ data: datos, convertTo: "pdf" },
|
||||
templateId,
|
||||
{ data: datos, ...extraBody },
|
||||
{ download: true },
|
||||
);
|
||||
|
||||
@@ -196,19 +246,37 @@ Deno.serve(async (req: Request): Promise<Response> => {
|
||||
{ action },
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
const error = err instanceof HttpError ? err : new HttpError(
|
||||
500,
|
||||
"Error interno del servidor.",
|
||||
"INTERNAL_SERVER_ERROR",
|
||||
} catch (error) {
|
||||
if (error instanceof HttpError) {
|
||||
console.error(
|
||||
`[${new Date().toISOString()}][${functionName}] ⚠️ Handled Error:`,
|
||||
{
|
||||
original: err instanceof Error
|
||||
? { message: err.message, stack: err.stack }
|
||||
: err,
|
||||
message: error.message,
|
||||
code: error.code,
|
||||
internalDetails: error.internalDetails || "N/A",
|
||||
},
|
||||
);
|
||||
|
||||
return sendError(error.status, error.message, error.code);
|
||||
}
|
||||
|
||||
const unexpectedError = error instanceof Error
|
||||
? error
|
||||
: new Error(String(error));
|
||||
|
||||
console.error(
|
||||
`[${
|
||||
new Date().toISOString()
|
||||
}][${functionName}] 💥 CRITICAL UNHANDLED ERROR:`,
|
||||
unexpectedError.stack || unexpectedError.message,
|
||||
);
|
||||
|
||||
return sendError(
|
||||
500,
|
||||
"Ocurrió un error inesperado en el servidor.",
|
||||
"INTERNAL_SERVER_ERROR",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
/* To invoke locally:
|
||||
|
||||
Reference in New Issue
Block a user