Files
HoruxDespachosNuevo/apps/api/src/services/documentos-extras.service.ts

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);
}