Files
CRM_AGENTES_CARGA/frontend/src/lib/api/fin/issuer.ts
Jair Cedillo 5a112a0171 feat(fin): pantallas de conceptos y datos fiscales del emisor
Clientes API por dominio para los catálogos del SAT, conceptos y emisor. Los
catálogos se cachean en un Map del módulo tras la primera carga: son fijos y no
cambian durante la sesión.

Pantalla de conceptos (/dashboard/fin/conceptos) con tabla, buscador, filtro de
activos y alta/edición en diálogo. La clave de producto/servicio se elige con un
combobox que consulta el catálogo a partir de 2 caracteres, y el 409 del backend
por clave ya asignada se muestra junto al campo.

Sección de configuración fiscal (/dashboard/settings/facturacion) con razón
social, RFC (misma validación que el backend), régimen fiscal y CP. Si el GET
responde 404 se abre en modo alta, no como error; el guardar se deshabilita sin
fin.settings.edit.

Todo en Svelte 5 con runes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-07 16:58:09 -05:00

52 lines
1.4 KiB
TypeScript

/**
* Cliente API — Datos fiscales del emisor (una configuración por empresa).
*/
import { api } from '$lib/api';
import type { SatTaxRegime } from './catalogs';
/** RFC de persona moral (3 letras) o física (4 letras) + fecha + homoclave. */
export const RFC_REGEX = /^[A-ZÑ&]{3,4}\d{6}[A-Z0-9]{3}$/;
export interface IssuerSettings {
id: number;
tenant_id: number;
company_id: number;
legal_name: string;
rfc: string;
tax_regime_id: number;
tax_regime: SatTaxRegime | null;
zip_code: string | null;
updated_by: string | null;
created_at: string;
updated_at: string;
}
export interface IssuerSettingsInput {
legal_name: string;
rfc: string;
tax_regime_id: number;
zip_code?: string | null;
}
export const issuerAPI = {
/**
* Devuelve `null` cuando la empresa todavía no captura sus datos fiscales: el
* backend responde 404 y la pantalla debe abrirse en modo alta, no en error.
*/
async get(companyId: number): Promise<IssuerSettings | null> {
const res = await api.get<IssuerSettings>(`/v1/fin/settings/issuer?company_id=${companyId}`);
if (res.status === 404) return null;
if (res.error) throw new Error(res.error);
return res.data!;
},
async save(data: IssuerSettingsInput, companyId: number): Promise<IssuerSettings> {
const res = await api.put<IssuerSettings>(
`/v1/fin/settings/issuer?company_id=${companyId}`,
data
);
if (res.error) throw new Error(res.error);
return res.data!;
}
};