Plataforma técnica · Sevastopol
Bancos Island
Islands Sevastopol Finanzas
Propósito
Section titled “Propósito”BancosIsland mantiene el maestro de cuentas bancarias del tenant y sus categorías. Pinta dos tablas CRUD, cada una con su modal. El saldo bancario que renderiza es efectivo — suma saldo inicial registrado más los aportes de capital asociados — y se calcula al cierre del mes activo (fecha_hasta).
Ubicación
Section titled “Ubicación”Directorysevastopol/src/components/islands/financieros/
- BancosIsland.tsx — componente único, internamente
BancosPanel - FinancierosWorkspace.tsx — tokens compartidos
- BancosIsland.tsx — componente único, internamente
Directorysevastopol/src/lib/hooks/
- useActiveTenant.ts
- useActivePeriod.ts
Composición
Section titled “Composición”Dos pestañas controladas por activeTab:
| Pestaña | Función | Modal |
|---|---|---|
bancos | Catálogo de cuentas bancarias del tenant. | Alta/edición con autocompletado desde catálogo local. |
categorias | Categorías que agrupan los bancos por tipo (Banco, Préstamo, Línea Crédito, Inversión, Otro). | Alta/edición con validación de cuenta contable padre. |
Hooks y estado global
Section titled “Hooks y estado global”const { tenantId } = useActiveTenant((id) => { void Promise.all([loadBancos(), loadCategorias(), loadCuentasContables(id)]);});
const { period } = useActivePeriod((p) => { if (p.year && p.month) setFechaHasta(lastDayStr(p.year, p.month)); void loadBancos();});| Hook | Aporta | Reactividad |
|---|---|---|
useActiveTenant | UUID del tenant. | Carga en paralelo bancos, categorías y plan de cuentas. |
useActivePeriod | { year, month }. | Mueve fechaHasta al último día del mes activo y recarga bancos para que el saldo refleje ese corte. |
function lastDayStr(year: number, month: number): string { const d = new Date(year, month, 0).getDate(); return `${year}-${String(month).padStart(2, "0")}-${String(d).padStart(2, "0")}`;}Signals locales:
| Signal | Tipo | Uso |
|---|---|---|
activeTab | "bancos" | "categorias" | Pestaña visible. |
fechaHasta | string (YYYY-MM-DD) | Corte para saldo_actual. |
bancos | Banco[] | Catálogo del tenant. |
categorias | CategoriaBancaria[] | Catálogo (incluye inactivas vía todas=true). |
cuentasContables | CuentaContableLite[] | Plan de cuentas imputables del tenant, para los selectores. |
filtroBanco / filtroCategoria | string | Filtros locales. |
showBancoModal / showCategoriaModal | boolean | Apertura de modales. |
editingBanco / editingCategoria | objeto o null | Distingue alta vs edición. |
bancoForm / categoriaForm | objetos planos | Estado del formulario activo. |
bancoCatalogoCodigo | string | Selección del catálogo local de bancos chilenos. |
Saldo inicial efectivo
Section titled “Saldo inicial efectivo”La columna Saldo Inicial renderiza un valor compuesto:
const efectivo = r.saldo_inicial_efectivo ?? r.saldo_inicial ?? 0;const aportes = Number(r.capital_aportes_total ?? 0);const registrado = Number(r.saldo_inicial ?? 0);const tooltip = aportes > 0 ? `Registrado: ${fmt(registrado)} + ${r.capital_aportes_count} aporte(s) de capital: ${fmt(aportes)}` : "Solo saldo inicial registrado (sin aportes de capital)";Cuando hay aportes (aportes > 0), aparece un sufijo (NC) en azul indicando cuántos aportes de capital componen el efectivo. La fórmula es registrado + aportes, y el tooltip explica la composición.
| Indicador visual | Significado |
|---|---|
| Sin sufijo | saldo_inicial_efectivo = saldo_inicial — no hay aportes. |
(3C) en azul | El efectivo incluye 3 aportes de capital adicionales al saldo registrado. |
Catálogo local de bancos chilenos
Section titled “Catálogo local de bancos chilenos”El modal de alta de banco incluye un selector pre-poblado con 10 bancos chilenos:
| Banco | RUT | Código |
|---|---|---|
| BancoEstado | 97.030.000-7 | 012 |
| Banco de Chile | 97.004.000-5 | 001 |
| Banco Santander | 97.036.000-K | 037 |
| Banco BCI | 97.006.000-6 | 016 |
| Scotiabank | 97.018.000-1 | 014 |
| Banco Itaú | 76.000.248-0 | 039 |
| Banco BICE | 97.080.000-K | 028 |
| Banco Security | 97.053.000-2 | 049 |
| Banco Falabella | 97.951.000-8 | 051 |
| Banco Consorcio | 99.500.000-9 | 055 |
Seleccionar uno autocompleta nombre, rut_banco y codigo_banco en el formulario:
function applyBancoCatalogo(codigo: string) { const banco = BANCOS_CATALOGO.find((item) => item.codigo_banco === codigo); if (!banco) return; setBancoForm((prev) => ({ ...prev, nombre: banco.nombre, rut_banco: banco.rut_banco, codigo_banco: banco.codigo_banco, }));}El catálogo no cubre todos los bancos del SBIF; basta no usar el autocompletado y escribir manualmente para los faltantes.
Modal de banco
Section titled “Modal de banco”| Campo | Tipo | Obligatorio | Notas |
|---|---|---|---|
| Catálogo bancos | <select> | No | Autocompleta nombre/RUT/código. |
nombre | <input> | Sí | — |
rut_banco | <input> | No | Formato XX.XXX.XXX-Y. |
codigo_banco | <input> | No | 3 dígitos del SBIF. |
categoria_id | <select> | Sí | Lista de categorías del tenant. |
numero_cuenta | <input> | Sí | — |
tipo_cuenta | <select> | Sí | CTA_CTE, AHORRO, VISTA, CAJA, OTRO. |
moneda | <input> | — | Default CLP, normalizado a uppercase. |
cuenta_contable_codigo | <select> | No | Heredada de la categoría seleccionada al crear; editable. |
saldo_inicial | <input type=number> | — | Default 0. |
fecha_saldo_inicial | <input type=date> | No | Opcional. |
observaciones | <textarea> | No | — |
function onBancoCategoriaChange(categoriaId: string) { const categoria = categorias().find((c) => String(c.id) === categoriaId); setBancoForm((prev) => ({ ...prev, categoria_id: categoriaId, cuenta_contable_codigo: editingBanco() ? prev.cuenta_contable_codigo : (categoria?.cuenta_contable_codigo ?? ""), }));}Herencia de cuenta contable: al crear un banco, cambiar la categoría sobrescribe cuenta_contable_codigo con el valor de la categoría. Al editar un banco existente, el cambio de categoría no sobrescribe — preserva la cuenta del banco para no romper la trazabilidad contable.
Modal de categoría
Section titled “Modal de categoría”| Campo | Tipo | Obligatorio | Notas |
|---|---|---|---|
codigo | <input> | Sólo en alta | Inmutable después de creada; normalizado a uppercase. |
nombre | <input> | Sí | — |
tipo | <select> | Sí | BANCO, PRESTAMO, LINEA_CREDITO, INVERSION, OTRO. |
cuenta_contable_codigo | <select> | Condicional | Obligatorio si el tipo está en el mapa de padres permitidos. |
descripcion | <textarea> | No | — |
activo | <checkbox> | — | Default true. |
Mapa de cuentas padre permitidas
Section titled “Mapa de cuentas padre permitidas”Cada tipo restringe qué cuenta contable es válida como padre:
const CUENTAS_PADRE_POR_TIPO: Record<string, string[]> = { BANCO: ["1101200"], INVERSION: ["1102000"], LINEA_CREDITO: ["2101000", "210100"], PRESTAMO: ["2101100", "2201000"],};| Tipo | Padre permitido | Significado |
|---|---|---|
BANCO | 1101200 | Bancos (activo corriente). |
INVERSION | 1102000 | Inversiones (activo corriente). |
LINEA_CREDITO | 2101000, 210100 | Pasivo corriente — créditos rotativos. |
PRESTAMO | 2101100, 2201000 | Pasivo corriente / no corriente. |
OTRO | (sin restricción) | Sin validación. |
El selector de cuenta contable se filtra contra estos padres usando el plan de cuentas (cuentasContables) cargado desde /api/admin/chart-of-accounts.
if (padresPermitidos.length > 0 && !f.cuenta_contable_codigo.trim()) { toast.error("Seleccione una cuenta contable para este tipo de categoría"); return;}Cascade de eliminación
Section titled “Cascade de eliminación”| Acción | Efecto colateral |
|---|---|
| Eliminar banco | Recarga sólo bancos. El backend rechaza si tiene movimientos. |
| Eliminar categoría | Recarga categorías y bancos en paralelo — los bancos enlazados quedan con nombre_categoria = null. |
Endpoints consumidos
Section titled “Endpoints consumidos”| Método | Ruta | Operación |
|---|---|---|
GET | /api/financieros/bancos?fecha_hasta&tenant_id | Lista del catálogo con saldo a fecha. |
POST | /api/financieros/bancos?tenant_id | Alta. |
PUT | /api/financieros/bancos/:id?tenant_id | Edición. |
DELETE | /api/financieros/bancos/:id?tenant_id | Eliminación. |
GET | /api/financieros/categorias?todas=true&tenant_id | Lista incluyendo inactivas. |
POST | /api/financieros/categorias?tenant_id | Alta. |
PUT | /api/financieros/categorias/:id?tenant_id | Edición. |
DELETE | /api/financieros/categorias/:id?tenant_id | Eliminación. |
GET | /api/admin/chart-of-accounts?tenant_id | Plan de cuentas imputables. |
Reglas de UI
Section titled “Reglas de UI”| Regla | Motivo |
|---|---|
fechaHasta se sigue al período activo | El saldo bancario es siempre al corte del mes contable, no a hoy. |
| Carga en paralelo al cambiar tenant | Bancos, categorías y plan de cuentas son independientes; serializar agrega latencia visible. |
| Categoría hereda cuenta contable sólo en alta | Cambiar categoría de un banco existente no debe alterar su cuenta contable — eso rompería el libro mayor. |
codigo de categoría inmutable post-creación | El código es referenciado por reglas externas; cambiarlo desincronizaría reportes. |
| Catálogo local de bancos chilenos | Acelera el alta del 80% de los casos sin necesidad de un endpoint extra. |
| Saldo inicial muestra efectivo + tooltip detallado | El operador necesita explicar la composición al auditor sin abrir un detalle. |
| Filtros locales por nombre / código / número | El catálogo es pequeño (menos de 50 cuentas por tenant); paginar no aporta. |
Errores con fallback a error.message ?? error.error | El backend a veces retorna {message}, a veces {error}; la UI lee ambos. |
| Eliminar categoría refresca bancos | Los bancos pueden quedar huérfanos visualmente (nombre_categoria = null); el refresh es necesario para reflejarlo. |