Fierro Acceso a Datos es un servicio que permite a los clientes consumir información de Sistema Fierro desde aplicaciones externas, tales como herramientas de Business Intelligence (BI), soluciones de reportería avanzada, sistemas logísticos u otros desarrollos propios. La solución se basa en la replicación periódica de la base de datos de producción, generando un entorno independiente sobre el cual se definen vistas de datos y usuarios con acceso exclusivo de lectura. Este enfoque garantiza que las consultas externas no interfieran con la operatoria diaria ni comprometan la integridad del sistema productivo. La frecuencia de actualización de la información se define en función de las limitaciones técnicas del entorno, priorizando la estabilidad y el correcto funcionamiento del sistema. El servicio ofrece: * Aislamiento total respecto de la base de producción * Accesos de solo lectura con control y seguridad * Vistas de datos estandarizadas, orientadas a consumo externo * Rendimiento optimizado para consultas analíticas
Las vistas disponibles forman parte de un conjunto estándar, que se irá ampliando y mejorando con el tiempo como parte de la evolución del producto. El desarrollo de vistas específicas o a medida puede contratarse como un servicio adicional. Fierro Acceso a Datos incluye la configuración inicial, el mantenimiento del proceso de replicación y el soporte técnico del servicio.
La base replicada puede alojarse en infraestructura de Fierro o en infraestructura provista por el cliente, según la modalidad contratada.
Todas las operaciones del sistema registran fecha, hora, usuario y sucursal de origen. El detalle de cada transacción se encuentra en la vista vw_transaction
Todos los documentos comparten una estructura base común, con campos estándar como fecha, hora, usuario y sucursal de origen. Todos los documentos están en la vista vw_document.
El detalle específico de cada tipo de documento se encuentra en las vistas correspondientes de cada módulo (ejemplo: vw_sale_document).
Muchos documentos del sistema tienen formas de pago. El detalle de las formas de pago se encuentra en la vista vw_payment.
Las personas y organizaciones comparten una estructura base común, con campos estándar como nombre, apellido, tipo de documento, número de documento, email, teléfono, dirección, etc. Las mismas están en la vista vw_party .
El detalle de clientes, proveedores, vendedores, etc. se encuentra en las vistas correspondientes de cada módulo (ejemplo: vw_client, vw_provider, vw_salesman).
Para los libros hay varias vistas de acuerdo a la utilidad que se necesite.
Las materias, para simplificar su estructura jerárquica, están en vw_materia.
Las ventas se encuentran en la vista vw_sale_document y vw_sale_item. Estas agrupan facturas y notas de crédito. Además, contienen parte de la información de los clientes y los libros para eventualmente evitar joins con esas vistas.
Para obtener un documento en detalle, se deben consultar las siguientes vistas: * vw_sale_document: cabecera del documento * vw_sale_item: items del documento * vw_payment: formas de pago del documento * vw_sale_tax: impuestos del documento * vw_sale_concept: adicionales del documento
vw_book consolida en una única salida el catálogo de libros con:
metadatos básicos (códigos, título, estado)
autores (concatenados)
materias (códigos y rutas jerárquicas via vw_materia)
proveedor principal (via vw_party)
precio vigente según lista definida por parámetro global parameter.key='PriceList'
stock consolidado (suma en depósitos)
auditoría (transacciones de creación/actualización)
*Performance: la vista incluye varias subconsultas correlacionadas (autores, materias, isbn/barcode, stock). Para listados masivos se recomienda filtrar/paginar.
TODO: búsqueda por ISBN optimizada
SELECT book_id, int_code, title, authors_full, price, stock_total, active
FROM public.vw_book
WHERE active = true
ORDER BY title
LIMIT 50 OFFSET 0;
SELECT *
FROM public.vw_book
WHERE isbn = '9789871234567'
OR int_code = 'INT-000123';
SELECT main_provider_party_id, main_provider_name, COUNT(*) AS books, SUM(stock_total) AS stock
FROM public.vw_book
WHERE main_provider_party_id IS NOT NULL
GROUP BY main_provider_party_id, main_provider_name
ORDER BY books DESC;
Vista orientada a auditoría y sincronización incremental del catálogo. Devuelve las fechas clave de actividad del libro y calcula global_last_modification_at como indicador único de “última modificación”.
SELECT book_id, int_code, title, global_last_modification_at
FROM public.vw_book_audit
WHERE global_last_modification_at > '2025-06-01'::timestamp
ORDER BY global_last_modification_at;
Este módulo expone el catálogo de libros mediante vistas SQL optimizadas para dos propósitos distintos:
Detección eficiente de cambios (auditoría / sincronización incremental)
Obtención del detalle completo del libro (catálogo enriquecido)
La separación de responsabilidades permite escalar el sistema sin penalizar consultas frecuentes ni procesos batch.
vw_book_audit — Auditoría y detección de cambios
Vista liviana orientada a control y sincronización. Expone las fechas clave de actividad de cada libro y calcula un único timestamp de referencia:
global_last_modification_at
Este campo representa la fecha más reciente entre:
creación o edición de la ficha del libro,
último cambio de precio (según la lista definida por el parámetro global PriceList),
último movimiento real de stock.
👉 Uso principal: detectar qué libros cambiaron desde una fecha/hora.
Vista enriquecida que consolida:
metadatos del libro,
autores (concatenados),
materias jerárquicas (vía vw_materia),
proveedor principal (vía vw_party),
stock consolidado,
precio vigente según PriceList,
auditoría.
👉 Uso principal: obtener todos los datos del libro para UI, APIs o exportaciones.
Consultar vw_book_audit para identificar los libros modificados desde la última sincronización.
Usar los book_id obtenidos para consultar vw_book.
Procesar los resultados en orden, permitiendo paginación y reintentos seguros.
Este patrón evita escanear todo el catálogo y reduce significativamente el costo de sincronización.
-- :since = timestamp de última sincronización
WITH changed_books AS (
SELECT book_id, global_last_modification_at
FROM public.vw_book_audit
WHERE global_last_modification_at > '2025-06-01 00:00:00'::timestamp
)
SELECT
vb.*,
cb.global_last_modification_at
FROM public.vw_book vb
JOIN changed_books cb ON cb.book_id = vb.book_id
ORDER BY cb.global_last_modification_at ASC, vb.book_id;
Recomendado para procesos batch o APIs.
-- Cursor compuesto: (last_sync_at, last_book_id)
WITH changed_books AS (
SELECT book_id, global_last_modification_at
FROM public.vw_book_audit
WHERE (global_last_modification_at, book_id)
> ('2025-06-01 00:00:00'::timestamp, 0)
ORDER BY global_last_modification_at, book_id
LIMIT 500
)
SELECT
vb.*,
cb.global_last_modification_at
FROM public.vw_book vb
JOIN changed_books cb ON cb.book_id = vb.book_id
ORDER BY cb.global_last_modification_at, vb.book_id;
Permite:
guardar el último cursor procesado,
retomar sin duplicar registros,
procesar catálogos grandes de forma segura.
Útil para colas de reprocesamiento o validaciones rápidas.
SELECT book_id, global_last_modification_at
FROM public.vw_book_audit
WHERE global_last_modification_at > '2025-06-01 00:00:00'::timestamp
ORDER BY global_last_modification_at, book_id;
⚠️ Importante: el campo isbn en vw_book es derivado. Para que PostgreSQL use índice, el filtro debe hacerse sobre book_isbn.
WITH changed_books AS (
SELECT book_id, global_last_modification_at
FROM public.vw_book_audit
WHERE global_last_modification_at > '2025-06-01 00:00:00'::timestamp
)
SELECT
vb.*,
cb.global_last_modification_at
FROM changed_books cb
JOIN public.book_isbn bi ON bi.book_id = cb.book_id
JOIN public.vw_book vb ON vb.book_id = cb.book_id
WHERE bi.isbn = '9789871234567'
ORDER BY cb.global_last_modification_at, vb.book_id;
vw_book_audit está pensada para ser liviana y usada frecuentemente.
vw_book incluye subconsultas correlacionadas (autores, materias, ISBN, stock).
Usar siempre con filtros (WHERE, LIMIT) o para un conjunto acotado de libros.
Recordar restricción de búsqueda por ISBN.
vw_client es una vista consolidada del rol Cliente, que combina:
Identidad base (desde public.vw_party): nombre, tipo, tax_id, IVA, contactos y ubicación.
Atributos comerciales (desde public.client y catálogos): tipo de cliente, cuenta corriente, límites, moneda, condición de venta, lista de precios, zona.
Vendedor asignado: resuelto como otra identidad (vw_party) a partir de client.salesman_id.
SELECT party_id, client_code, legalname, tax_id, has_account
FROM public.vw_client
WHERE client_code = 'CL-000123';
SELECT client_code, name, sell_condition_name, price_list_name, salesman_name
FROM public.vw_client
ORDER BY name
LIMIT 50;
SELECT client_code, legalname, credit_limit, limit_currency_symbol
FROM public.vw_client
WHERE has_account = true
AND credit_limit IS NOT NULL
ORDER BY credit_limit DESC
LIMIT 100;
SELECT
salesman_id,
salesman_name,
COUNT(*) AS client_qty
FROM public.vw_client
WHERE salesman_id IS NOT NULL
GROUP BY salesman_id, salesman_name
ORDER BY client_qty DESC;
vw_document es la vista base para consulta, auditoría y reporting de documentos del sistema. Abstrae la tabla public.document y enriquece cada registro con:
nombres legibles de tipo de documento (document_type_name),
una familia/grupo funcional (document_group) derivada de reglas de negocio,
información de sucursal,
auditoría completa de la transacción que originó el documento (usuario y fecha).
El mapeo de tipos y grupos se realiza mediante un CTE embebido (doc_types), que refleja directamente los enums utilizados en el código de la aplicación.
Importante: para los reportes lo más probable es que no se use esta vista, sino las vistas particulares de cada módulo. Esta vista se utiliza para simplificar la construcción de documentos en otras vistas.
Todos los documentos tienen fecha pero no todos tienen fecha contable. Dentro del sistema, si un documento no tiene fecha contable, se toma la fecha real como fecha contable.
Tipo de documento
Representado por document_type_id (valor numérico).
Traducido a document_type_name (ej: SALE_BILL, BUY_ORDER).
Agrupa documentos por función de negocio, facilitando filtros y reportes masivos.
Ejemplos de grupos:
BUY_ORDER
BUY_BILL
SALE_BILL
SALE_ORDER
SALE_PAYMENT
STOCK
BOOKKEEPING
RRMM_LIQUIDATION
PERSONAL
PERSONAL_PAYMENT
SELECT
document_id,
real_date,
document_type_name,
sucursal_name
FROM public.vw_document
WHERE document_group = 'STOCK'
ORDER BY real_date DESC;
SELECT
document_id,
document_type_name,
real_date,
account_date,
sucursal_name
FROM public.vw_document
WHERE document_group IN ('SALE_BILL', 'SALE_CREDIT_NOTE')
AND real_date BETWEEN '2025-01-01' AND '2025-01-31'
ORDER BY account_date;
SELECT
document_id,
document_type_name,
document_group,
transaction_date
FROM public.vw_document
WHERE user_id = 42
ORDER BY transaction_date DESC;
SELECT
sucursal_name,
document_group,
COUNT(*) AS qty
FROM public.vw_document
WHERE real_date >= NOW() - INTERVAL '7 days'
GROUP BY sucursal_name, document_group
ORDER BY sucursal_name, qty DESC;
Útil para control contable/impositivo.
SELECT
document_id,
document_type_name,
real_date,
account_date
FROM public.vw_document
WHERE real_date <> account_date
ORDER BY real_date DESC;
SELECT
transaction_date,
operator_name,
document_type_name,
sucursal_name
FROM public.vw_document
ORDER BY transaction_date DESC
LIMIT 100;
vw_document no reemplaza a public.document: la enriquece para lectura.
El mapeo de tipos está hardcodeado en la vista y debe mantenerse sincronizado con el enum del código.
Si un document_type_id no está contemplado en el mapeo:
document_type_name y document_group pueden quedar NULL
esto sirve como señal de desalineación entre base y aplicación.
vw_transaction: aporta auditoría (usuario y fecha).
vw_book_audit: utiliza real_date y transaction_date para calcular cambios globales.
vw_book: depende indirectamente de documentos para stock y precios.
vw_materia expone el catálogo de materias como una jerarquía (árbol). Cada fila representa una materia y su relación padre/hijo, además de un campo full_path que describe la ruta completa desde una materia raíz hasta el nodo.
Contrato importante: la jerarquía debe ser acíclica (sin bucles en materia_padre_id).
SELECT materia_id, code, full_path
FROM public.vw_materia
ORDER BY full_path;
SELECT materia_id, full_path
FROM public.vw_materia
WHERE full_path ILIKE '%Historia%'
ORDER BY full_path;
SELECT *
FROM public.vw_materia
WHERE full_path LIKE (
SELECT full_path || '%'
FROM public.vw_materia
WHERE materia_id = 123
)
ORDER BY full_path;
vw_party es la vista base para trabajar con identidades (“party”) en el sistema. Unifica en una única salida tanto Personas como Organizaciones.
Las vistas de clientes, proveedores, vendedores y otros roles se construyen sobre esta vista.
Temas que resuelve:
Tipo de party (persona/organización)
Nombres “legal” y “comercial”
Identificación fiscal
Condición de IVA
Contactos principales (email y teléfono)
Ubicación principal (dirección, ciudad, provincia, país, CP)
Trazabilidad por transacción (creación y última actualización)
party_type_id: 1 = Persona, 2 = Organización.
legalname: "Apellido, Nombre"
name: "Nombre Apellido"
legalname: razón social (organization.legalname)
name: nombre de fantasía (organization.name)
Las direcciones que se muestran son las que corresponden al tipo de dirección principal.
SELECT party_id, party_type_name, legalname, tax_id
FROM public.vw_party
WHERE tax_id = '20304050607';
SELECT party_id, name, primary_email, primary_phone, city, province, country
FROM public.vw_party
ORDER BY name
LIMIT 50;
SELECT party_type_name, COUNT(*) AS qty
FROM public.vw_party
GROUP BY party_type_name
ORDER BY qty DESC;
Vista consolidada para reportes de pagos por medio, banco, sucursal y operador. Recomendada para:
arqueos de caja/banco
conciliaciones
reportes por medio de pago y fechas
obtener el detalle de la forma de pago de un documento específico
SELECT payment_type_name, SUM(amount_converted) AS total_base
FROM public.vw_payment
WHERE document_date >= NOW() - INTERVAL '90 days'
GROUP BY payment_type_name
ORDER BY total_base DESC;
SELECT bank_name, SUM(amount_converted) AS total_base
FROM public.vw_payment
WHERE bank_name IS NOT NULL
AND document_date >= NOW() - INTERVAL '90 days'
GROUP BY bank_name
ORDER BY total_base DESC;
SELECT sucursal_name, operator_name, COUNT(*) AS qty, SUM(amount_converted) AS total_base
FROM public.vw_payment
WHERE document_date >= NOW() - INTERVAL '90 days'
GROUP BY sucursal_name, operator_name
ORDER BY total_base DESC;
vw_provider es la vista consolidada del rol Proveedor, que combina:
SELECT party_id, provider_code, legalname, tax_id
FROM public.vw_provider
WHERE provider_code = 'PR-000123';
SELECT provider_code, name, buy_condition_name, pay_term, order_gen_strategy_name
FROM public.vw_provider
ORDER BY name
LIMIT 50;
SELECT provider_code, legalname, use_cost, shipping_cost_pct, return_cost_pct
FROM public.vw_provider
WHERE use_cost = true
ORDER BY legalname;
vw_sale_concept expone los cargos y descuentos aplicados a documentos de venta que no corresponden a productos, como:
fletes
recargos financieros
descuentos comerciales
cargos administrativos
La vista unifica conceptos de Facturas Y conceptos de Notas de Crédito y devuelve los montos contablemente firmados, listos para sumarizar.
Útil para comparar lo facturado contra lo que realmente nos cobra el transporte.
SELECT
SUM(amount) AS recaudacion_fletes
FROM public.vw_sale_concept
WHERE concept_name ILIKE '%FLETE%'
AND real_date BETWEEN '2025-05-01' AND '2025-05-31';
Para saber qué conceptos están impactando más en la facturación total.
SELECT
concept_name,
COUNT(*) as cantidad_usos,
SUM(amount) as total_neto
FROM public.vw_sale_concept
WHERE real_date BETWEEN '2025-01-01' AND '2025-01-02'
GROUP BY concept_name
ORDER BY total_neto DESC;
Si tienes un concepto de "Descuento Especial" o "Bonificación", puedes auditar quiénes lo están recibiendo y bajo qué observación.
SELECT
real_date,
observation,
amount
FROM public.vw_sale_concept
WHERE amount < 0 -- Los descuentos resultan en montos negativos
ORDER BY real_date DESC;
Si quieres ver qué se le cobró a un cliente además de los libros en la factura ID 1500:
SELECT concept_name, observation, amount
FROM public.vw_sale_concept
WHERE document_id = 1500;
vw_sale_document unifica facturas (SALE_BILL) y notas de crédito (SALE_CREDIT_NOTE) en un esquema común para reporting y exportación. Incluye:
identificación legal (legal_number)
cliente y vendedor (desde vw_client / vw_salesman)
moneda y tipo de cambio histórico (exchange_rate)
totales firmados (ventas positivas, NC negativas)
desgloses agregados: IVA (vw_sale_tax) y conceptos (vw_sale_concept)
Regla de signo
Factura: sign = 1
Nota de crédito: sign = -1
Todos los totales permiten sumarizar sin CASE.
Importante:
La columna is_cancelled indica si el comprobante fue anulado. Los comprobantes anulados no deben incluirse en los reportes de ventas netas.
Todos los documentos tienen fecha pero no todos tienen fecha contable. Dentro del sistema, si un documento no tiene fecha contable, se toma la fecha real como fecha contable.
SELECT
account_date,
legal_number,
client_tax_id,
client_name,
total_net_taxable,
total_vat,
total_amount
FROM public.vw_sale_document
WHERE real_date BETWEEN '2025-01-01' AND '2025-01-31'
ORDER BY account_date, legal_number;
SELECT
SUM(total_amount) AS sales_net_total
FROM public.vw_sale_document
WHERE real_date BETWEEN '2025-01-01' AND '2025-01-31'
AND is_cancelled IS NOT TRUE;
SELECT
client_party_id,
client_name,
SUM(total_amount) AS total
FROM public.vw_sale_document
WHERE real_date >= '2025-01-01'
AND is_cancelled IS NOT TRUE
GROUP BY client_party_id, client_name
ORDER BY total DESC;
SELECT
salesman_party_id,
salesman_name,
SUM(total_amount) AS total
FROM public.vw_sale_document
WHERE real_date >= '2025-01-01'
AND is_cancelled IS NOT TRUE
GROUP BY salesman_party_id, salesman_name
ORDER BY total DESC;
SELECT
real_date,
legal_number,
document_type_name,
sucursal_name,
operator_name,
total_amount
FROM public.vw_sale_document
ORDER BY real_date DESC
LIMIT 100;
SELECT
legal_number,
currency_symbol,
exchange_rate,
total_amount,
total_amount_base
FROM public.vw_sale_document
WHERE real_date >= NOW() - INTERVAL '7 days'
ORDER BY real_date DESC;
Para auditar qué sucursales tienen más errores o cancelaciones.
SELECT
sucursal_name,
COUNT(*) FILTER (WHERE is_cancelled = true) AS cantidad_anuladas,
COUNT(*) FILTER (WHERE is_cancelled = false) AS cantidad_validas,
ROUND((COUNT(*) FILTER (WHERE is_cancelled = true) * 100.0 / COUNT(*)), 2) AS pct_error
FROM public.vw_sale_document
GROUP BY sucursal_name;
SELECT
c.country,
SUM(d.total_amount_base) AS total_sales_base
FROM public.vw_sale_document d
JOIN public.vw_client c
ON d.client_party_id = c.party_id
WHERE d.real_date BETWEEN DATE '2026-01-01' AND DATE '2026-01-31'
AND d.is_cancelled IS NOT TRUE
GROUP BY c.country
ORDER BY total_sales_base DESC;
```sql
# Detalle de líneas de venta: vw_sale_item
vw_sale_item entrega una fila por cada ítem vendido/devolución, unificando facturas y notas de crédito.
Los importes y cantidades están con su correspondiente signo, por lo que pueden agregarse directamente.
## Casos de uso y queries
### 1) Top libros vendidos por cantidad (período)
```sql
SELECT
b.title,
SUM(si.quantity) AS qty
FROM public.vw_sale_item si
JOIN public.vw_book b ON si.book_id = b.book_id
WHERE si.report_date BETWEEN DATE '2025-01-01' AND DATE '2025-08-31'
GROUP BY b.title
ORDER BY qty DESC
LIMIT 20;
SELECT
salesman_name,
SUM(line_total_neto_base) AS subtotal_base
FROM public.vw_sale_item
WHERE report_date BETWEEN DATE '2025-01-01' AND DATE '2025-08-31'
GROUP BY salesman_name
ORDER BY subtotal_base DESC;
SELECT
c.country,
SUM(si.line_total_neto_base) AS subtotal_base
FROM public.vw_sale_item si
JOIN public.vw_sale_document sd ON si.document_id = sd.document_id
JOIN public.vw_client c ON sd.client_party_id = c.party_id
WHERE si.report_date >= DATE '2025-01-01'
GROUP BY c.country
ORDER BY subtotal_base DESC;
SELECT
legal_number,
client_name,
SUM(line_total_neto_base) AS refund_base
FROM public.vw_sale_item
WHERE sign = -1
AND report_date >= DATE '2025-01-01'
GROUP BY legal_number, client_name
ORDER BY refund_base ASC;
SELECT
report_date,
legal_number,
client_name,
title,
quantity,
unit_price,
discount_pct,
line_total_neto,
currency_symbol
FROM public.vw_sale_item
ORDER BY report_date DESC
LIMIT 50;
Al tener esta documentación y estructura, puedes generar el Reporte Impositivo Mensual de forma directa.
Ejemplo:
SELECT
aliquot_name,
percentage,
SUM(net_amount) AS total_neto_gravado,
SUM(tax_amount) AS total_iva_debito
FROM public.vw_sale_tax
WHERE real_date BETWEEN '2025-05-01' AND '2025-05-31'
GROUP BY
aliquot_name,
percentage
ORDER BY
percentage DESC;
vw_salesman expone el catálogo de vendedores consolidando:
identidad base desde vw_party (nombres, tax_id y contacto),
datos comerciales del rol vendedor (salesman_code, comisiones),
zona geográfica asignada (tabla zone).
SELECT party_id, salesman_code, legalname, zone_name, primary_phone
FROM public.vw_salesman
ORDER BY legalname;
SELECT zone_name, COUNT(*) AS qty
FROM public.vw_salesman
GROUP BY zone_name
ORDER BY qty DESC;
SELECT
c.salesman_id,
c.salesman_name,
COUNT(*) AS client_qty
FROM public.vw_client c
WHERE c.salesman_id IS NOT NULL
GROUP BY c.salesman_id, c.salesman_name
ORDER BY client_qty DESC;
public.vw_transaction es una vista de trazabilidad/auditoría que consolida registros de la tabla public.transaction y los enriquece con información de contexto (usuario y sucursal).
Además, convierte el campo numérico transaction_type en un nombre legible (transaction_type_name) mediante un mapeo embebido en la propia vista.
Cuando un tipo no está contemplado en el mapeo, se expone como UNKNOWN, lo cual permite detectar rápidamente tipos nuevos o inconsistencias entre base y aplicación.
Todas las entidades y documentos del sistema tienen su transacción. Se deberá acceder a esta vista para obtener su detalle.
Estado actual: además del PK transaction_id, la tabla public.transaction no tiene índices sobre transaction_date, user_id, sucursal_id ni transaction_type.
Si se quiere acceder por fecha, usuario, sucursal o tipo de transacción, se recomienda crear índices para mejorar el rendimiento de las consultas.