# Inventory

- Tipo: Modulo core/base de Vtiger CRM 8.4.0
- Criticidad: Critica
- Complejidad: Alta
- Prioridad: P1 funcional antes de cualquier cambio sobre compras, ventas, facturacion o stock
- Estado: Operativo con riesgos estructurales controlables
- Health Score: 78/100
- Ubicacion principal: `admin/modules/Inventory/`
- Ultima actualizacion: 2026-06-26 14:19:53 CST

## Resumen funcional

`Inventory` no es un modulo de inventario aislado. En esta instalacion funciona como capa comun para documentos comerciales de Vtiger: `Quotes`, `SalesOrder`, `PurchaseOrder` e `Invoice`. Centraliza line items, seleccion de productos/servicios, impuestos, descuentos, cargos, totales, moneda, PDF y parte del movimiento de existencias.

La alta y edicion de productos ocurre en `Products`; `Inventory` consume esos productos y servicios como partidas dentro de documentos comerciales. Las existencias se modifican de forma indirecta desde documentos:

- Entrada: `PurchaseOrder` incrementa stock al cambiar a `Received Shipment`.
- Salida: `Invoice` descuenta stock cuando no esta cancelada.
- Reversion: cancelacion/restauracion de `Invoice` y cancelacion de `PurchaseOrder` ajustan stock segun estado previo.
- Consulta: `Products` mantiene `qtyinstock` y expone relaciones hacia cotizaciones, ordenes, compras y facturas.

## Arquitectura

### Controllers y actions

- `actions/Save.php`: extiende `Vtiger_Save_Action`; delega guardado al mecanismo base.
- `actions/SaveAjax.php`: extiende `Vtiger_SaveAjax_Action`.
- `actions/MassSave.php`: guarda cambios masivos evitando borrar partidas al forzar `ajxaction=DETAILVIEW`.
- `actions/GetTaxes.php`: endpoint Ajax para impuestos, precios, moneda, costo, descripcion, stock e imagen de productos/servicios.
- `actions/ExportPDF.php`: valida permiso de detalle y genera PDF del documento.
- `actions/BasicAjax.php`: hereda comportamiento Ajax base.

### Models

- `models/Record.php`: modelo central de documento. Calcula productos relacionados, impuestos, cargos, moneda, totales, descuentos y conversiones de visualizacion.
- `models/Module.php`: configuracion de modulo, summary view, comentarios, monedas, impuestos y query de exportacion.
- `models/TaxRecord.php`: administra impuestos de productos/servicios y shipping. Incluye capacidad de agregar columnas a tablas de inventario cuando se crean impuestos.
- `models/TaxRegion.php`: regiones fiscales.
- `models/Charges.php`: cargos de inventario y sus impuestos.
- `models/ListView.php`, `DetailView.php`, `RelationListView.php`, `EditRecordStructure.php`, `FilterRecordStructure.php`, `MassEditRecordStructure.php`: estructura de vistas, relaciones y listados.

### Views, templates y JavaScript

- `views/Edit.php`: arma formulario de creacion/edicion, hereda datos desde Quote/SalesOrder/Invoice/PurchaseOrder, carga productos/servicios, impuestos, moneda, cargos y terminos.
- `views/Detail.php`: prepara line items para vista detalle, formatea moneda, impuestos, cargos y totales.
- `views/List.php`, `views/Popup.php`, `ProductsPopup*`, `ServicesPopup*`, `SubProductsPopup*`: listados y seleccion de partidas.
- `layouts/v7/modules/Inventory/partials/LineItemsEdit.tpl`: estructura principal de partidas editables.
- `layouts/v7/modules/Inventory/partials/LineItemsContent.tpl`: fila de producto/servicio, cantidad, precio, descuento, impuestos, margen y alerta de stock.
- `layouts/v7/modules/Inventory/LineItemsDetail.tpl`: render de partidas en detalle.
- `layouts/v7/modules/Inventory/resources/Edit.js`: calculos client-side de line items, descuentos, impuestos, moneda, direcciones y totales.
- `layouts/v7/modules/Inventory/resources/Detail.js`: vista rapida, preview PDF y popovers.
- `layouts/v7/modules/Inventory/resources/Popup.js`: busqueda y seleccion de productos/subproductos.

### Dependencias directas

- `include/utils/InventoryUtils.php`: persistencia de partidas, impuestos, cargos y actualizacion de stock.
- `Products`: alta/edicion/consulta de productos, stock, impuestos, moneda, subproductos y relaciones.
- `Services`: servicios como partidas sin stock fisico.
- `Quotes`, `SalesOrder`, `PurchaseOrder`, `Invoice`: documentos que usan la capa Inventory.
- `PriceBooks`: precios alternativos por producto/servicio.
- `PDFMaker`/controladores PDF de Vtiger: salida PDF segun plantillas.

## Flujo funcional certificado

### Alta de producto

El alta real pertenece a `Products`, no a `Inventory`. `Products::save_module()` persiste impuestos en `vtiger_producttaxrel`, precios en `vtiger_productcurrencyrel` y mantiene `unit_price`. Luego el producto puede ser insertado en documentos de inventario mediante popups o autocompletado.

### Edicion de producto

La edicion de producto actualiza datos base, impuestos y precios. Los documentos existentes conservan sus partidas en `vtiger_inventoryproductrel`; no se recalculan automaticamente todos los historicos por editar el producto.

### Consulta

La consulta de documentos usa `Inventory_Record_Model::getProducts()` y `getAssociatedProducts()` para reconstruir partidas, impuestos, descuentos, cargos, totales, imagenes y moneda.

### Existencias y movimientos

El stock fisico vive en `Products` (`qtyinstock`). `Inventory` solo lo altera indirectamente:

- `PurchaseOrder`: cuando el estado pasa a `Received Shipment`, suma cantidades a stock.
- `PurchaseOrder`: si se cancela despues de recepcion, revierte cantidades.
- `Invoice`: al guardar una factura activa, descuenta cantidades de stock.
- `Invoice`: si se cancela o elimina, devuelve cantidades al stock.
- Subproductos: `vtiger_inventorysubproductrel` permite descontar/sumar componentes asociados.

### Entradas

Las entradas operativas se modelan con `PurchaseOrder`. La recepcion efectiva ocurre por estado, no por un modulo separado de movimientos.

### Salidas

Las salidas operativas se modelan con `Invoice`. `SalesOrder` administra demanda comercial, pero el descuento de stock esta centrado en factura.

### Relacion con compras

`PurchaseOrder` extiende el esquema Inventory con tablas propias (`vtiger_purchaseorder`, direcciones, custom fields) y usa `saveInventoryProductDetails()` para guardar partidas. El estado `Received Shipment` es el disparador critico de entrada.

### Relacion con ventas

`Quotes` y `SalesOrder` usan Inventory para cotizacion y orden comercial. `Invoice` usa Inventory para factura y salida de stock. `SalesOrder` puede actualizar demanda; `Invoice` impacta existencia.

## Base de datos inferida por lectura

Tablas centrales:

- `vtiger_inventoryproductrel`: partidas por documento, producto/servicio, cantidad, precio, descuento, impuestos, costo, margen.
- `vtiger_inventorysubproductrel`: componentes/subproductos vinculados a una partida.
- `vtiger_inventoryshippingrel`: impuestos/cargos historicos de envio.
- `vtiger_inventorychargesrel`: cargos serializados por documento.
- `vtiger_inventorycharges`: catalogo de cargos.
- `vtiger_inventorytaxinfo`: impuestos de productos/servicios.
- `vtiger_shippingtaxinfo`: impuestos de shipping/cargos.
- `vtiger_producttaxrel`: impuestos por producto/servicio.
- `vtiger_productcurrencyrel`: precios por moneda.
- `vtiger_products`, `vtiger_productcf`: productos y campos custom.
- `vtiger_service`, `vtiger_servicecf`: servicios y campos custom.

Tablas de documentos:

- `vtiger_quotes`, `vtiger_quotescf`, `vtiger_quotesbillads`, `vtiger_quotesshipads`.
- `vtiger_salesorder`, `vtiger_salesordercf`, `vtiger_sobillads`, `vtiger_soshipads`, `vtiger_invoice_recurring_info`.
- `vtiger_purchaseorder`, `vtiger_purchaseordercf`, `vtiger_pobillads`, `vtiger_poshipads`.
- `vtiger_invoice`, `vtiger_invoicecf`, `vtiger_invoicebillads`, `vtiger_invoiceshipads`.
- `vtiger_crmentity`: entidad comun, ownership, borrado logico y metadatos.

Indices relevantes esperados por uso del codigo:

- `vtiger_inventoryproductrel.id`
- `vtiger_inventoryproductrel.productid`
- `vtiger_inventoryproductrel.lineitem_id`
- `vtiger_inventorysubproductrel.id`
- `vtiger_inventorysubproductrel.sequence_no`
- claves primarias por documento (`quoteid`, `salesorderid`, `purchaseorderid`, `invoiceid`)
- `vtiger_crmentity.crmid`

## Integraciones internas

- `Products`: productos, stock, imagenes, subproductos, impuestos y precios.
- `Services`: partidas de servicio sin control de stock fisico.
- `Quotes`: cotizaciones con line items, impuestos y totales.
- `SalesOrder`: ordenes de venta y demanda.
- `PurchaseOrder`: compras y entradas de stock.
- `Invoice`: facturacion y salidas/reversiones de stock.
- `PriceBooks`: precios seleccionables en line items.
- `Logistica`: no se detecto acoplamiento directo con `Inventory` en los archivos revisados; la relacion parece indirecta por procesos comerciales.

## Seguridad

- Los actions revisados heredan control de permisos de Vtiger.
- `GetTaxes` declara permiso sobre `sourceModule` con `DetailView`.
- `ExportPDF` exige permiso de `DetailView` sobre el registro.
- Los formularios purifican valores con helpers de Vtiger en persistencia de partidas.
- Riesgo residual: mucha logica depende de parametros `$_REQUEST`; cualquier cambio debe conservar validacion server-side, no solo JavaScript.

## Rendimiento

- El guardado de partidas usa multiples consultas por linea para impuestos, subproductos, precios y stock.
- `GetTaxes` procesa listas de ids y carga modelos por registro; puede degradar con seleccion masiva.
- Popups de Products/Services dependen de busquedas y permisos sobre tablas potencialmente grandes.
- La vista detalle recalcula/formatea line items completos y puede ser pesada en documentos con muchas partidas.

## Personalizaciones Gravimex

No se detectaron personalizaciones directas con marca Gravimex dentro de `admin/modules/Inventory` ni `layouts/v7/modules/Inventory` durante esta revision. La personalizacion operacional parece vivir en modulos externos como `Logistica` y `WSAPP`, sin dependencia directa confirmada hacia `Inventory` en los archivos revisados.

## Reglas para cambios futuros

Antes de modificar este modulo se debe probar, como minimo:

- crear producto y servicio;
- crear/editar Quote con producto y servicio;
- convertir Quote a SalesOrder/Invoice si aplica;
- crear PurchaseOrder y pasar a `Received Shipment`;
- crear Invoice y validar descuento de stock;
- cancelar Invoice y validar reversion;
- validar impuestos individuales y grupales;
- validar descuentos por linea y globales;
- validar PDF;
- validar permisos por perfil no administrador.
