- New reports backend (registry, service, controller, outputs, types) with catalog endpoint + slug/CSV/XLSX/PDF/print outputs. - /reportes catalog + /reportes/[slug] runner; ReportRunner + ContextReports components wire pre-filtered links from domain pages. - Fix: /reportes/[slug] now reads searchParams and forwards initialParams to ReportRunner so /reportes/edo-cuenta-datos?customerId=... auto-runs instead of dropping the id and forcing a manual customer search. - /inicio landing page; root + login redirect to /inicio. - Company header env vars + logo asset for PDF/print rendering. - exceljs + pdfkit deps.
104 lines
3.4 KiB
TypeScript
104 lines
3.4 KiB
TypeScript
/**
|
|
* Company info used on every report header (PDF + print). Read from
|
|
* the environment so the office can edit it without a code change —
|
|
* the .env.example file lists the keys; defaults below are placeholders
|
|
* the office should override for production.
|
|
*
|
|
* Single source of truth: the API renders the header. The web header
|
|
* (login + AppShell) still reads the static "Jorge Cuadros & Asociados"
|
|
* strings for now — those are visual brand, the API's COMPANY_INFO
|
|
* block is the legal/locator block on printed documents.
|
|
*/
|
|
|
|
import * as fs from "node:fs";
|
|
import * as path from "node:path";
|
|
|
|
export interface CompanyInfo {
|
|
name: string;
|
|
/** Street address — line 1. */
|
|
addressLine1: string;
|
|
/** Street address — line 2 (suite, floor, etc.). Optional. */
|
|
addressLine2: string;
|
|
/** "City, State, ZIP, Country" — single line. */
|
|
cityState: string;
|
|
phone: string;
|
|
email: string;
|
|
/** Mexican tax ID ("RFC"). Optional. */
|
|
taxId: string;
|
|
website: string;
|
|
/** Absolute path to the logo PNG. Null when missing — renderers fall
|
|
* back to a text mark. */
|
|
logoPath: string | null;
|
|
/** Logo buffer + intrinsic size, eagerly loaded so the PDF renderer
|
|
* doesn't do a sync read on every report. Null when no logo. */
|
|
logo: { buffer: Buffer; width: number; height: number } | null;
|
|
}
|
|
|
|
function envOr(key: string, fallback: string): string {
|
|
const v = process.env[key];
|
|
return v && v.trim() ? v : fallback;
|
|
}
|
|
|
|
function resolveLogoPath(): string | null {
|
|
const explicit = process.env.COMPANY_LOGO_PATH;
|
|
if (explicit) {
|
|
return fs.existsSync(explicit) ? explicit : null;
|
|
}
|
|
// Default: look in apps/api/assets/company_logo.png (copied from
|
|
// apps/web/public/images/company_logo.png — single canonical image
|
|
// kept in lock-step; see .env.example for the override path).
|
|
const candidates = [
|
|
path.resolve(__dirname, "..", "..", "assets", "company_logo.png"),
|
|
path.resolve(__dirname, "..", "..", "..", "web", "public", "images", "company_logo.png"),
|
|
];
|
|
for (const c of candidates) {
|
|
if (fs.existsSync(c)) return c;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
let cached: CompanyInfo | null = null;
|
|
|
|
export function getCompanyInfo(): CompanyInfo {
|
|
if (cached) return cached;
|
|
const logoPath = resolveLogoPath();
|
|
let logo: CompanyInfo["logo"] = null;
|
|
if (logoPath) {
|
|
try {
|
|
const buf = fs.readFileSync(logoPath);
|
|
// Intrinsic PNG size: read IHDR (bytes 16-23 of the file).
|
|
// Width = BE uint32 at offset 16, height = BE uint32 at offset 20.
|
|
const w =
|
|
logoPath.endsWith(".png") && buf.length >= 24
|
|
? buf.readUInt32BE(16)
|
|
: 0;
|
|
const h =
|
|
logoPath.endsWith(".png") && buf.length >= 24
|
|
? buf.readUInt32BE(20)
|
|
: 0;
|
|
logo = { buffer: buf, width: w, height: h };
|
|
} catch {
|
|
logo = null;
|
|
}
|
|
}
|
|
cached = {
|
|
name: envOr("COMPANY_NAME", "Jorge Cuadros & Asociados"),
|
|
addressLine1: envOr(
|
|
"COMPANY_ADDRESS_LINE1",
|
|
"Av. Revolución 1234, Int. 5",
|
|
),
|
|
addressLine2: envOr("COMPANY_ADDRESS_LINE2", ""),
|
|
cityState: envOr(
|
|
"COMPANY_CITY_STATE",
|
|
"Tijuana, Baja California 22000, México",
|
|
),
|
|
phone: envOr("COMPANY_PHONE", "(664) 000-0000"),
|
|
email: envOr("COMPANY_EMAIL", "contacto@jorgecuadros.local"),
|
|
taxId: envOr("COMPANY_TAX_ID", ""),
|
|
website: envOr("COMPANY_WEBSITE", "jorgecuadros.local"),
|
|
logoPath,
|
|
logo,
|
|
};
|
|
return cached;
|
|
}
|