fix: personalización logo/color por contribuyente en vez de tenant
- Agrega getCustomizationContribuyente, uploadLogoContribuyente, updateColorContribuyente en contribuyente-facturapi.service.ts - Agrega controllers per-contribuyente en facturacion.controller.ts - Agrega rutas GET/POST/PUT /contribuyentes/:id/facturapi/customization|logo|color - Modifica CustomizationSection para recibir contribuyenteId, usar endpoints per-contribuyente, y corrige useState mal aplicado a useEffect - Backend y frontend buildeados y deployados
This commit is contained in:
@@ -542,3 +542,66 @@ async function ensureOrgLegalForEmit(
|
||||
const payload = await buildLegalPayload(contrib, chosenTaxSystem, currentLegal);
|
||||
await putOrgLegal(orgId, payload);
|
||||
}
|
||||
|
||||
// ── Personalización (logo, color) per-contribuyente ──
|
||||
|
||||
export async function getCustomizationContribuyente(
|
||||
pool: Pool,
|
||||
contribuyenteId: string,
|
||||
): Promise<{ logoUrl?: string; color?: string } | null> {
|
||||
const { rows } = await pool.query<{ facturapi_org_id: string }>(
|
||||
'SELECT facturapi_org_id FROM facturapi_orgs WHERE contribuyente_id = $1 AND active = true',
|
||||
[contribuyenteId],
|
||||
);
|
||||
if (rows.length === 0) return null;
|
||||
|
||||
const userClient = getUserClient();
|
||||
try {
|
||||
const org = await userClient.organizations.retrieve(rows[0].facturapi_org_id);
|
||||
return {
|
||||
logoUrl: org.customization?.has_logo ? (org.logo_url ?? undefined) : undefined,
|
||||
color: org.customization?.color || undefined,
|
||||
};
|
||||
} catch { return null; }
|
||||
}
|
||||
|
||||
export async function uploadLogoContribuyente(
|
||||
pool: Pool,
|
||||
contribuyenteId: string,
|
||||
logoBase64: string,
|
||||
): Promise<{ success: boolean; message: string }> {
|
||||
const { rows } = await pool.query<{ facturapi_org_id: string }>(
|
||||
'SELECT facturapi_org_id FROM facturapi_orgs WHERE contribuyente_id = $1 AND active = true',
|
||||
[contribuyenteId],
|
||||
);
|
||||
if (rows.length === 0) throw new Error('Organización no configurada');
|
||||
|
||||
const userClient = getUserClient();
|
||||
try {
|
||||
const buffer = Buffer.from(logoBase64, 'base64');
|
||||
await userClient.organizations.uploadLogo(rows[0].facturapi_org_id, buffer);
|
||||
return { success: true, message: 'Logo subido correctamente' };
|
||||
} catch (error: any) {
|
||||
return { success: false, message: error.message || 'Error al subir logo' };
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateColorContribuyente(
|
||||
pool: Pool,
|
||||
contribuyenteId: string,
|
||||
color: string,
|
||||
): Promise<{ success: boolean; message: string }> {
|
||||
const { rows } = await pool.query<{ facturapi_org_id: string }>(
|
||||
'SELECT facturapi_org_id FROM facturapi_orgs WHERE contribuyente_id = $1 AND active = true',
|
||||
[contribuyenteId],
|
||||
);
|
||||
if (rows.length === 0) throw new Error('Organización no configurada');
|
||||
|
||||
const userClient = getUserClient();
|
||||
try {
|
||||
await userClient.organizations.updateCustomization(rows[0].facturapi_org_id, { color });
|
||||
return { success: true, message: 'Color actualizado correctamente' };
|
||||
} catch (error: any) {
|
||||
return { success: false, message: error.message || 'Error al actualizar color' };
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user