Contabilización de Activo Fijo en Sevastopol
Sevastopol · Activo Fijo
Activo fijoSevastopolUI
Propósito
Section titled “Propósito”Las pestañas Activos y Categorías de ActivosFijosIsland cubren el reconocimiento inicial del bien: dar de alta las categorías que parametrizan la contabilidad y dar de alta cada activo, opcionalmente enlazado a la compra SII que lo originó.
Esta página documenta el flujo frontend actual. La validación y la persistencia viven en Orchestrator; Sevastopol actúa como interfaz operativa y proxy hacia /api/activo-fijo.
Ubicación
Section titled “Ubicación”Directorysevastopol/src/components/islands/contabilidad/
- ActivosFijosIsland.tsx
Directorysevastopol/src/pages/api/activo-fijo/
- index.ts
- […path].ts
Relación con la Vista
Section titled “Relación con la Vista”ActivosFijosIsland contiene tres pestañas. Esta página cubre las dos primeras.
| Pestaña | Función |
|---|---|
activos | Consulta activos, da de alta un activo nuevo y administra su baja. |
categorias | Administra categorías tributarias, vida útil y cuentas contables. |
depreciacion | Consulta, genera, contabiliza, reversa o elimina cuotas. Ver Depreciación en Sevastopol. |
Las pestañas dependen del tenant activo. La constante de API es AF_API = "/api/activo-fijo".
Estado del Formulario de Alta
Section titled “Estado del Formulario de Alta”const [showCrearActivo, setShowCrearActivo] = createSignal(false);const [crearActivoForm, setCrearActivoForm] = createSignal({ categoria_id: '', nombre: '', descripcion: '', numero_serie: '', ubicacion: '', responsable: '', rut_proveedor: '', compra_id: '', monto_neto: '', iva: '', valor_residual: '0', fecha_compra: '', fecha_inicio_dep: '',});Flujo de Alta de Activo
Section titled “Flujo de Alta de Activo”-
Abrir el modal de alta. Antes de mostrarlo se cargan las compras disponibles, la tabla de vida útil y las categorías.
await loadCompras(tid);await loadVidaUtil();await loadCategorias(tid);resetCrearForm();setShowCrearActivo(true); -
Validar los campos obligatorios antes de enviar.
const f = crearActivoForm();if (!f.categoria_id || !f.nombre || !f.monto_neto || !f.fecha_compra) {toast.push('Completa los campos obligatorios', 'error');return;} -
Construir el cuerpo de la solicitud. La fecha de inicio de depreciación se iguala a la fecha de compra.
const fechaInicioDep = f.fecha_compra;const body: Record<string, any> = {categoria_id: Number(f.categoria_id),nombre: f.nombre.trim(),rut_proveedor: f.rut_proveedor.trim(),monto_neto: Number(f.monto_neto),fecha_compra: f.fecha_compra,fecha_inicio_dep: fechaInicioDep,}; -
Si se eligió una compra de origen, completar los datos desde la línea de compra.
if (f.compra_id) {const compra = compras().find((c) => c.id === f.compra_id);if (compra) {body.compra_id = compra.id;body.rut_proveedor = compra.rut_emisor ?? body.rut_proveedor;body.compra_año = compra.año;body.compra_mes = compra.mes;if (compra.folio) body.folio_factura = String(compra.folio);}} -
Enviar el alta al proxy local y recargar la lista de activos.
const r = await authenticatedFetch(`${AF_API}/activos?tenant_id=${tid}`, {method: 'POST',headers: { 'Content-Type': 'application/json' },body: JSON.stringify(body),});await handleAuthResponse(r);if (r.ok) {toast.push('Activo creado correctamente', 'success');setShowCrearActivo(false);await loadActivos(tid);}
Origen desde una Compra SII
Section titled “Origen desde una Compra SII”El campo compra_id es opcional. Cuando se completa, su valor es el id (UUID) de la línea de compras_ventas_detalle, no el identificador del documento de compra. loadCompras consulta las líneas disponibles:
async function loadCompras(tid: string) { if (!tid) return; const r = await authenticatedFetch(`${AF_API}/compras?tenant_id=${tid}`); await handleAuthResponse(r); if (r.ok) setCompras(await r.json());}Al enviar el compra_id, Orchestrator marca esa línea como contabilizada con referencia a activo fijo, lo que impide que el mismo documento se impute además como gasto.
Flujo de Alta de Categoría
Section titled “Flujo de Alta de Categoría”-
Validar todos los campos obligatorios, incluida la selección SII.
if (!f.nombre ||!f.seccion_sii ||!f.numero_item_sii ||!f.vida_util_anos ||!f.dep_acelerada_anos ||!f.cuenta_activo_codigo ||!f.cuenta_dep_acumulada_codigo ||!f.cuenta_gasto_dep_codigo) {toast.push('Completa todos los campos obligatorios (incluye selección SII)', 'error');return;} -
Construir el cuerpo con la vida útil y las tres cuentas contables.
const body: Record<string, any> = {nombre: f.nombre.trim(),seccion_sii: f.seccion_sii,vida_util_anos: Number(f.vida_util_anos),dep_acelerada_anos: Number(f.dep_acelerada_anos),cuenta_activo_codigo: f.cuenta_activo_codigo.trim(),cuenta_dep_acumulada_codigo: f.cuenta_dep_acumulada_codigo.trim(),cuenta_gasto_dep_codigo: f.cuenta_gasto_dep_codigo.trim(),}; -
Enviar la categoría y recargar el listado.
const r = await authenticatedFetch(`${AF_API}/categorias?tenant_id=${tid}`, {method: 'POST',headers: { 'Content-Type': 'application/json' },body: JSON.stringify(body),});await handleAuthResponse(r);if (r.ok) {toast.push('Categoría creada', 'success');setShowCrearCat(false);await loadCategorias(tid);}
Las cuentas contables de la categoría se eligen desde el plan contable del tenant, filtradas por cuentas padre fijas (1201000 para activo, 1202000 para depreciación acumulada).
Edición y Baja
Section titled “Edición y Baja”| Acción | Endpoint | Notas |
|---|---|---|
| Editar categoría | PUT /api/activo-fijo/categorias/:id | Actualiza nombre, vida útil, cuentas y bandera activo. |
| Dar de baja un activo | PUT /api/activo-fijo/activos/:id/baja | Envía estado (DADO_DE_BAJA o VENDIDO), fecha_baja y motivo_baja opcional. |
La baja exige fecha y solo procede sobre activos en estado ACTIVO; el resultado se valida por la respuesta de Orchestrator.
Columnas Visibles
Section titled “Columnas Visibles”Pestaña activos:
| Columna | Origen |
|---|---|
| Activo | nombre |
| Categoría | nombre_categoria |
| Compra | fecha_compra |
| Monto Neto | monto_neto |
| Valor Libro | valor_libro_actual |
| Depreciado | pct_depreciado |
| Estado | estado |
Endpoints
Section titled “Endpoints”| Método | Ruta | Operación |
|---|---|---|
GET | /api/activo-fijo/activos | Lista activos por estado. |
POST | /api/activo-fijo/activos | Da de alta un activo. |
PUT | /api/activo-fijo/activos/:id/baja | Da de baja un activo. |
GET | /api/activo-fijo/categorias | Lista categorías (todas=true incluye inactivas). |
POST | /api/activo-fijo/categorias | Crea una categoría. |
PUT | /api/activo-fijo/categorias/:id | Actualiza una categoría. |
GET | /api/activo-fijo/compras | Lista compras SII disponibles para alta. |
Proxy Local
Section titled “Proxy Local”Sevastopol no llama directamente a Orchestrator desde la island. La ruta src/pages/api/activo-fijo/[...path].ts reenvía método, query string, cookies, Authorization y cuerpo hacia Orchestrator.
let targetUrl = `${ORCHESTRATOR_BASE_URL}/api/activo-fijo/${restPath}`;if (url.search) targetUrl += url.search;
const orchestratorRes = await fetch(targetUrl, { method: request.method, headers: getProxyHeaders(request), body, credentials: 'include',});Reglas de UI
Section titled “Reglas de UI”| Regla | Motivo |
|---|---|
| Usar tenant activo | Los activos y categorías pertenecen a una base tenant. |
| Cargar compras al abrir el alta | El activo puede enlazarse a la línea de compra que lo originó. |
Igualar fecha_inicio_dep a fecha_compra | El flujo actual inicia la depreciación en la fecha de adquisición. |
| Crear la categoría antes que el activo | El activo exige una categoría existente que parametrice sus cuentas. |
| Recargar después de cada acción | Mantiene la tabla alineada con el estado de Orchestrator. |