130 lines
3.6 KiB
TypeScript
130 lines
3.6 KiB
TypeScript
import type { Pool } from 'pg';
|
|
|
|
export interface DocumentoExtra {
|
|
id: number;
|
|
contribuyenteId: string | null;
|
|
nombre: string;
|
|
descripcion: string | null;
|
|
categoria: string | null;
|
|
pdfFilename: string;
|
|
subidoPor: string | null;
|
|
createdAt: string;
|
|
}
|
|
|
|
interface CreateExtraInput {
|
|
contribuyenteId?: string | null;
|
|
nombre: string;
|
|
descripcion?: string | null;
|
|
categoria?: string | null;
|
|
pdfBase64: string;
|
|
pdfFilename: string;
|
|
subidoPor: string;
|
|
}
|
|
|
|
function sanitizeUuid(id: string): string {
|
|
return id.replace(/[^a-f0-9-]/gi, '');
|
|
}
|
|
|
|
export async function createExtra(
|
|
pool: Pool,
|
|
data: CreateExtraInput,
|
|
): Promise<DocumentoExtra> {
|
|
const pdfBuffer = Buffer.from(data.pdfBase64, 'base64');
|
|
const contribuyenteId = data.contribuyenteId
|
|
? sanitizeUuid(data.contribuyenteId)
|
|
: null;
|
|
const { rows } = await pool.query(
|
|
`INSERT INTO documentos_extras
|
|
(contribuyente_id, nombre, descripcion, categoria, pdf, pdf_filename, subido_por)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
RETURNING id, contribuyente_id AS "contribuyenteId", nombre, descripcion,
|
|
categoria, pdf_filename AS "pdfFilename", subido_por AS "subidoPor",
|
|
created_at AS "createdAt"`,
|
|
[
|
|
contribuyenteId,
|
|
data.nombre,
|
|
data.descripcion ?? null,
|
|
data.categoria ?? null,
|
|
pdfBuffer,
|
|
data.pdfFilename,
|
|
data.subidoPor,
|
|
],
|
|
);
|
|
const r = rows[0];
|
|
return { ...r, createdAt: r.createdAt?.toISOString?.() ?? r.createdAt };
|
|
}
|
|
|
|
export async function listExtras(
|
|
pool: Pool,
|
|
contribuyenteId?: string | null,
|
|
categoria?: string | null,
|
|
): Promise<DocumentoExtra[]> {
|
|
const params: any[] = [];
|
|
const where: string[] = [];
|
|
if (contribuyenteId) {
|
|
params.push(sanitizeUuid(contribuyenteId));
|
|
where.push(`contribuyente_id = $${params.length}`);
|
|
}
|
|
if (categoria) {
|
|
params.push(categoria);
|
|
where.push(`categoria = $${params.length}`);
|
|
}
|
|
const whereClause = where.length ? `WHERE ${where.join(' AND ')}` : '';
|
|
const { rows } = await pool.query(
|
|
`SELECT id, contribuyente_id AS "contribuyenteId", nombre, descripcion,
|
|
categoria, pdf_filename AS "pdfFilename", subido_por AS "subidoPor",
|
|
created_at AS "createdAt"
|
|
FROM documentos_extras
|
|
${whereClause}
|
|
ORDER BY created_at DESC
|
|
LIMIT 500`,
|
|
params,
|
|
);
|
|
return rows.map((r: any) => ({
|
|
...r,
|
|
createdAt: r.createdAt?.toISOString?.() ?? r.createdAt,
|
|
}));
|
|
}
|
|
|
|
export async function getExtraPdf(
|
|
pool: Pool,
|
|
id: number,
|
|
): Promise<{ buffer: Buffer; filename: string; nombre: string } | null> {
|
|
const { rows } = await pool.query(
|
|
`SELECT pdf, pdf_filename AS "pdfFilename", nombre
|
|
FROM documentos_extras WHERE id = $1`,
|
|
[id],
|
|
);
|
|
if (rows.length === 0) return null;
|
|
return {
|
|
buffer: rows[0].pdf,
|
|
filename: rows[0].pdfFilename,
|
|
nombre: rows[0].nombre,
|
|
};
|
|
}
|
|
|
|
export async function deleteExtra(pool: Pool, id: number): Promise<boolean> {
|
|
const { rowCount } = await pool.query(
|
|
`DELETE FROM documentos_extras WHERE id = $1`,
|
|
[id],
|
|
);
|
|
return (rowCount ?? 0) > 0;
|
|
}
|
|
|
|
export async function listCategorias(
|
|
pool: Pool,
|
|
contribuyenteId?: string | null,
|
|
): Promise<string[]> {
|
|
const params: any[] = [];
|
|
let where = `WHERE categoria IS NOT NULL AND categoria != ''`;
|
|
if (contribuyenteId) {
|
|
params.push(sanitizeUuid(contribuyenteId));
|
|
where += ` AND contribuyente_id = $${params.length}`;
|
|
}
|
|
const { rows } = await pool.query(
|
|
`SELECT DISTINCT categoria FROM documentos_extras ${where} ORDER BY categoria`,
|
|
params,
|
|
);
|
|
return rows.map((r: any) => r.categoria);
|
|
}
|