Plataforma técnica · Sevastopol
Config Contable View Island
Islands Sevastopol Administración
Propósito
Section titled “Propósito”ConfigContableViewIsland mantiene el wiring contable del tenant: qué cuenta usar por tipo de documento SII y qué débito/crédito por concepto operacional. Dos pestañas CRUD comparten el catálogo del plan de cuentas y se cargan en paralelo.
Ubicación
Section titled “Ubicación”Directorysevastopol/src/components/islands/admin/
- ConfigContableViewIsland.tsx — componente único, internamente
ConfigContableView
- ConfigContableViewIsland.tsx — componente único, internamente
Composición
Section titled “Composición”Dos pestañas controladas por tab:
| Pestaña | Tabla SQL | Identidad | Acciones |
|---|---|---|---|
cuentas | config_cuentas_contables | tipo_documento (VENTA, BOLETA, COMPRA) | Alta / Editar / Eliminar |
conceptos | config_conceptos_contables | concepto_codigo (string libre del catálogo de conceptos) | Alta / Editar / Eliminar |
Carga: 3 fetches en paralelo
Section titled “Carga: 3 fetches en paralelo”async function loadAll(tid: string) { const [rCuentas, rConceptos, rPlan] = await Promise.all([ authenticatedFetch(`${API_BASE}/cuentas?tenant_id=${tid}`), authenticatedFetch(`${API_BASE}/conceptos?tenant_id=${tid}`), authenticatedFetch(`${PLAN_API}?tenant_id=${tid}`), ]); if (!rCuentas.ok || !rConceptos.ok || !rPlan.ok) { throw new Error("Error cargando configuración contable"); } setCuentas(await rCuentas.json()); setConceptos(await rConceptos.json()); setPlanCuentas(await rPlan.json());}El plan de cuentas alimenta los selectores de ambas pestañas. Un solo fallo en cualquiera lanza error — la UI no carga parcialmente.
Helpers derivados
Section titled “Helpers derivados”const planOptions = createMemo(() => planCuentas().map((p) => ({ id: p.codigo, nombre: `${p.codigo} — ${p.nombre}` })),);
const cuentaLookup = createMemo(() => { const map = new Map<string, string>(); for (const p of planCuentas()) map.set(p.codigo, p.nombre); return map;});planOptions: opciones del<Select>con etiquetacódigo — nombre.cuentaLookup: mapa código → nombre para mostrar nombres legibles en la tabla sin re-buscar.
Pestaña Cuentas
Section titled “Pestaña Cuentas”Una fila por tipo de documento SII. El tipo_documento es la primary key (no hay UUID): editar reemplaza el registro completo.
const url = editing ? `${API_BASE}/cuentas/${editing.tipo_documento}?tenant_id=${tid}` : `${API_BASE}/cuentas?tenant_id=${tid}`;const method = editing ? "PUT" : "POST";const body = editing ? { cuenta_contable_codigo: f.cuenta_contable_codigo } : f;Al editar, el body solo manda cuenta_contable_codigo — el tipo es inmutable (es la identidad del registro y va en la URL). En la creación se manda todo el form.
Opciones de tipo: VENTA, BOLETA, COMPRA (constantes hardcodeadas, no enum del backend).
Pestaña Conceptos
Section titled “Pestaña Conceptos”Una fila por concepto operacional. La identidad es concepto_codigo. Cada concepto requiere dos cuentas: débito y crédito.
| Campo | Obligatorio | Notas |
|---|---|---|
concepto_codigo | Sólo en alta | String libre. Inmutable post-creación. |
cuenta_debito_codigo | Sí | Selector contra planOptions. |
cuenta_credito_codigo | Sí | Selector contra planOptions. |
La validación es simple — los tres campos no vacíos:
if (!f.concepto_codigo || !f.cuenta_debito_codigo || !f.cuenta_credito_codigo) { toast.push("Completa todos los campos", "error"); return;}El backend valida que ambas cuentas existan en el plan y que el concepto_codigo exista en operaciones_sii.conceptos_operaciones.
Endpoints consumidos
Section titled “Endpoints consumidos”| Método | Ruta | Operación |
|---|---|---|
GET | /api/admin/config-contable/cuentas?tenant_id | Lista de wiring por documento. |
POST | /api/admin/config-contable/cuentas?tenant_id | Alta de wiring. |
PUT | /api/admin/config-contable/cuentas/:tipo_documento?tenant_id | Reemplaza cuenta del tipo. |
DELETE | /api/admin/config-contable/cuentas/:tipo_documento?tenant_id | Elimina wiring. |
GET | /api/admin/config-contable/conceptos?tenant_id | Lista de conceptos. |
POST | /api/admin/config-contable/conceptos?tenant_id | Alta. |
PUT | /api/admin/config-contable/conceptos/:concepto_codigo?tenant_id | Actualiza débito/crédito. |
DELETE | /api/admin/config-contable/conceptos/:concepto_codigo?tenant_id | Elimina. |
GET | /api/admin/chart-of-accounts?tenant_id | Plan de cuentas para los selectores. |
Reglas de UI
Section titled “Reglas de UI”| Regla | Motivo |
|---|---|
| Identidad por código natural (no UUID) | El tipo_documento y el concepto_codigo son referenciados por código en SQL; usar UUID requeriría joins innecesarios. |
| Carga en paralelo | Los 3 endpoints son independientes; serializar es latencia visible. |
| Edición solo del campo no-identidad | El tipo/código de un registro nunca cambia — si hace falta, se elimina y se crea otro. |
| Confirmación destructiva en DELETE | Eliminar wiring rompe la contabilización del próximo asiento que use ese tipo/concepto. |
Selector con etiqueta código — nombre | Acelera la búsqueda visual; los códigos solos son crípticos para conceptos contables. |
| Sin recarga entre pestañas | El cambio de pestaña usa los datos ya en memoria; ambas pestañas trabajan sobre el mismo snapshot del plan. |
| Toast unificado con `err.error |