Skip to content

Contabilización de Activo Fijo en Sevastopol

Sevastopol · Activo Fijo

Activo fijoSevastopolUI

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.

  • Directorysevastopol/src/components/islands/contabilidad/
    • ActivosFijosIsland.tsx
  • Directorysevastopol/src/pages/api/activo-fijo/
    • index.ts
    • […path].ts

ActivosFijosIsland contiene tres pestañas. Esta página cubre las dos primeras.

PestañaFunción
activosConsulta activos, da de alta un activo nuevo y administra su baja.
categoriasAdministra categorías tributarias, vida útil y cuentas contables.
depreciacionConsulta, 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".

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: '',
});
  1. 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);
  2. 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;
    }
  3. 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,
    };
  4. 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);
    }
    }
  5. 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);
    }

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.

  1. 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;
    }
  2. 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(),
    };
  3. 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).

AcciónEndpointNotas
Editar categoríaPUT /api/activo-fijo/categorias/:idActualiza nombre, vida útil, cuentas y bandera activo.
Dar de baja un activoPUT /api/activo-fijo/activos/:id/bajaEnví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.

Pestaña activos:

ColumnaOrigen
Activonombre
Categoríanombre_categoria
Comprafecha_compra
Monto Netomonto_neto
Valor Librovalor_libro_actual
Depreciadopct_depreciado
Estadoestado
MétodoRutaOperación
GET/api/activo-fijo/activosLista activos por estado.
POST/api/activo-fijo/activosDa de alta un activo.
PUT/api/activo-fijo/activos/:id/bajaDa de baja un activo.
GET/api/activo-fijo/categoriasLista categorías (todas=true incluye inactivas).
POST/api/activo-fijo/categoriasCrea una categoría.
PUT/api/activo-fijo/categorias/:idActualiza una categoría.
GET/api/activo-fijo/comprasLista compras SII disponibles para alta.

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',
});
ReglaMotivo
Usar tenant activoLos activos y categorías pertenecen a una base tenant.
Cargar compras al abrir el altaEl activo puede enlazarse a la línea de compra que lo originó.
Igualar fecha_inicio_dep a fecha_compraEl flujo actual inicia la depreciación en la fecha de adquisición.
Crear la categoría antes que el activoEl activo exige una categoría existente que parametrice sus cuentas.
Recargar después de cada acciónMantiene la tabla alineada con el estado de Orchestrator.