Appearance
Lista de Precios - Costo por Margen de Ganancia - Documentacion Tecnica Frontend
DOCUMENTACION RETROSPECTIVA - Generada a partir de codigo implementado el 2026-02-09
Modulo: Ventas Feature: Lista de Precios - Costo por Margen de Ganancia Fecha: 2026-02-09
Referencia de Negocio
Estado de la Implementacion: Legacy (Vanilla JS + PHP)
Esta funcionalidad esta implementada con la arquitectura legacy del sistema:
- Vista: PHP server-side rendering (
lista-precios-costo-ganancia.php) - Logica: Vanilla JavaScript con ES Modules (
lista-precios-ganancia-margen.js) - API: Legacy
ApiRequestclass (FormData + fetch via proxy PHP) - UI Framework: AdminLTE 3 + Bootstrap 4 + jQuery + jQuery UI
- NO migrada a React/TypeScript
Archivos Involucrados
| Archivo | Tipo | Proposito |
|---|---|---|
public/view/mod-ventas/lista-precios-costo-ganancia.php | Vista PHP | Template HTML con formulario |
public/js/view/mod-ventas/lista-precios-ganancia-margen.js | JavaScript ES Module | Logica del formulario y llamadas API |
public/php/backend/lista-precio.php | Proxy PHP | Proxy legacy entre frontend y backend |
public/php/components/mod-venta/main-sidebar-venta.php | Sidebar PHP | Menu de navegacion del modulo Ventas |
Componentes de la Vista
Template PHP: lista-precios-costo-ganancia.php
Estructura de pagina:
- Header con breadcrumb: Home > Ventas > Lista precios > Costo por margen de ganancia
- Card con titulo "Costo por margen de ganancia"
- Formulario con ID
idFormListaPrecios - Footer estandar
- Scripts cargados: jQuery, Bootstrap, DataTables, AdminLTE, jQuery UI
Formulario HTML:
idFormListaPrecios (form)
|
|-- Radio buttons (name="aplicacion")
| |-- idInputPorcentajeArticulo: "Aplicar % Ganancia registrado en el articulo" [checked]
| |-- idInputPorcentajeFijo: "Aplicar % Fijo"
| |-- idInputPorcentaje: input text (disabled por defecto) [data-badge-type="P"]
|
|-- idInputLista: input number - "Lista" [required]
|
|-- idCheckPrecioFinal: checkbox - "Obtener Precio Final (Costo + Impuestos)"
|
|-- idInputAgrupacionDesde: input text - "Desde agrupacion" [con autocomplete]
|-- idInputAgrupacionHasta: input text - "Hasta agrupacion" [con autocomplete]
|
|-- idBtnRegistrar: button submit - "Aceptar"
|-- button "Cancelar" (onclick="back('mv')")Logica JavaScript
Archivo: lista-precios-ganancia-margen.js
Imports:
ApiRequestdesde../../middleware/API.js- Clase para comunicacion con backendsetAutocompletedesde../../util/inputs.js- Configuracion de jQuery UI AutocompletesetInputBadgedesde../../util/inputs.js- Badge visual para inputs de porcentaje
Estructura de datos
Objeto actualizacionLista (estado local del formulario):
| Propiedad | Tipo | Valor inicial | Descripcion |
|---|---|---|---|
agrupacionDesde | int/null | null | ID del rubro inicial |
agrupacionHasta | int/null | null | ID del rubro final |
lista | int/null | null | Numero de lista destino |
porcentaje | float/null | null | Porcentaje fijo (null = usar del articulo) |
precioFinal | boolean | false | Incluir impuestos en calculo |
Flujo de inicializacion (IIFE asincrono)
- Muestra popup de carga
- Obtiene primer rubro:
GET rubro?first=true - Obtiene ultimo rubro:
GET rubro?last=true - Asigna valores por defecto a
actualizacionLista.agrupacionDesdeyagrupacionHasta - Muestra en inputs:
"{id} | {concepto}" - Configura autocomplete en ambos inputs de agrupacion
- Cierra popup de carga
Eventos configurados
| Elemento | Evento | Accion |
|---|---|---|
Radio porcentajeFijo | change | Habilita input porcentaje, asigna valor |
Radio porcentajeGanancia | change | Deshabilita input porcentaje, porcentaje = null |
idCheckPrecioFinal | change | Toggle precioFinal |
idInputPorcentaje | blur | Asigna valor a actualizacionLista.porcentaje |
idInputLista | blur | Asigna valor a actualizacionLista.lista |
idFormListaPrecios | submit | Ejecuta generacion |
Autocomplete de agrupaciones
Se configura jQuery UI Autocomplete en ambos campos:
Source: GET rubro?filter={term}&scope=min
Formato: { label: "{id} | {concepto}", value: { id, concepto } }
Al seleccionar: Asigna el ID a actualizacionLista.agrupacionDesde o agrupacionHasta
Al borrar: Asigna null
Submit del formulario
javascript
POST lista-precio
{
method: 'ganancia-margen',
data: actualizacionLista
}Flujo:
preventDefault()- Muestra popup "Generando lista de precios"
- Envia POST via
ApiRequest - En exito: muestra modal "Lista de precio generada"
- En error: manejo global de errores de
ApiRequest
Integracion con Backend (API)
Endpoints consumidos
| Metodo | Endpoint Legacy | Endpoint Backend Real | Proposito |
|---|---|---|---|
| GET | php/backend/rubro (via ApiRequest) | N/A (proxy) | Obtener rubros para autocomplete |
| POST | php/backend/lista-precio | POST /api/mod-ventas/lista-precio | Generar lista de precios |
Proxy PHP: lista-precio.php
Archivo: public/php/backend/lista-precio.php
El frontend no se comunica directamente con el backend Slim. Las requests pasan por el proxy PHP legacy:
Flujo GET:
- Lee parametros de
$_GET(lista, producto) - Valida con validator inline
- Reenvia a backend via
Request::get('mod-ventas/lista-precio', ['json' => $data]) - Retorna
datadel response JSON
Flujo POST:
- Lee body JSON desde
php://input - Reenvia a backend via
Request::post('mod-ventas/lista-precio', ['json' => $body]) - Retorna
datadel response JSON
Seguridad del proxy: Valida sesion ($_SESSION['SD_USER'])
Navegacion y Menu
Ubicacion en sidebar
Ventas (Mod. Ventas)
|-- Bases [permiso: VENTAS_BASES]
|-- Lista de precios [permiso: VENTAS_BASES_LISTA-PRECIO]
|-- Automatico por rango [permiso: VENTAS_BASES_LISTA-PRECIO_RANGO]
|-- Costo por margen de ganancia [permiso: VENTAS_BASES_LISTA-PRECIO_COSTO]URL
?loc=mvlpcg
Activacion de menu
Se activa manualmente via JavaScript inline al final del PHP template:
- Menu "Bases":
menu-is-opening,menu-open,active - Submenu "Lista de precios":
menu-is-opening,menu-open - Item activo:
idMainSideBarListaPreciosCostoPMargencon claseactive
Validaciones del Formulario
Validaciones HTML nativas
| Campo | Validacion | Tipo |
|---|---|---|
idInputLista | required | HTML5 |
Validaciones JavaScript
| Validacion | Ubicacion | Descripcion |
|---|---|---|
| Porcentaje habilitado/deshabilitado | Evento change de radios | Input porcentaje se deshabilita cuando se selecciona "por articulo" |
Validaciones ausentes
- No se valida que
listasea un numero positivo en el frontend - No se valida que las agrupaciones desde/hasta sean validas (que desde <= hasta)
- No se valida que el porcentaje sea un numero positivo
- No hay confirmacion previa antes de la ejecucion masiva
Dependencias Frontend
Librerias utilizadas
| Libreria | Version | Uso |
|---|---|---|
| jQuery | (bundled) | DOM manipulation, eventos |
| Bootstrap 4 | (bundled) | Estilos, grid, form-control |
| jQuery UI | (bundled) | Autocomplete en campos de agrupacion |
| SweetAlert2 | (global) | Popups de carga y mensajes (showPopupLoading, showModal, Swal) |
| AdminLTE | (bundled) | Layout, sidebar, cards |
| DataTables | Cargado pero no usado | Script incluido en template pero no utilizado por esta vista |
Funciones globales utilizadas
| Funcion | Origen | Uso |
|---|---|---|
showPopupLoading(tipo, mensaje) | Global (SweetAlert wrapper) | Popup de carga |
showModal(tipo, mensaje) | Global (SweetAlert wrapper) | Mensaje de exito/error |
Swal.close() | SweetAlert2 | Cerrar popup |
back(loc) | Global | Navegacion al menu (onclick del boton Cancelar) |
setAutocomplete(input, config) | ../../util/inputs.js | Configuracion de jQuery UI Autocomplete |
setInputBadge(input, required) | ../../util/inputs.js | Badge visual de porcentaje |
Diagrama de Interaccion
mermaid
sequenceDiagram
participant U as Usuario
participant V as Vista PHP
participant JS as lista-precios-ganancia-margen.js
participant P as Proxy PHP (lista-precio.php)
participant B as Backend (ListaPrecioController)
participant S as ListaPrecioService
participant M as ListaPrecio Model
participant D as Domain (Item/Ajuste)
Note over V,JS: Carga inicial
JS->>P: GET rubro?first=true
P-->>JS: Primer rubro
JS->>P: GET rubro?last=true
P-->>JS: Ultimo rubro
JS->>V: Renderiza rubros en inputs
Note over U,JS: Configuracion
U->>V: Selecciona modo porcentaje
U->>V: Ingresa lista destino
U->>V: Marca/desmarca precio final
U->>V: Ajusta agrupaciones (opcional)
Note over U,B: Ejecucion
U->>V: Click "Aceptar"
JS->>P: POST lista-precio {method: "ganancia-margen", data: {...}}
P->>B: POST /api/mod-ventas/lista-precio
B->>S: generarListaMargenGanancia(...)
loop Para cada producto del rango
S->>S: Verificar costo > 0
S->>S: Calcular precio base
opt Si precioFinal
S->>D: Item.calculate() con Ajustes
D-->>S: Precio final con impuestos
end
S->>M: getAll (verificar existencia)
alt No existe en lista
S->>M: insert(ListaPrecioDTO)
else Ya existe
S->>M: update(ListaPrecioDTO)
end
end
S-->>B: true/false
B-->>P: 201 Created
P-->>JS: Response
JS->>V: Muestra "Lista de precio generada"Consideraciones de Migracion a React
Esta funcionalidad es candidata a migracion a React/TypeScript. Aspectos a considerar:
Lo que se migraria
- Vista: De PHP template a componente React con React Hook Form + Zod
- API: De
ApiRequestlegacy a Axios con interceptores + TanStack Query - Autocomplete: De jQuery UI a componente
ControlledAutoCompletedel core - Validaciones: De HTML5 nativo + ausentes a Zod schema completo
- Feedback: De SweetAlert global a sistema de notificaciones de React
Estructura sugerida post-migracion
ts/ventas/ListaPrecio/
|-- components/
| |-- CostoGananciaForm/
| |-- index.tsx
|-- views/
| |-- CostoGananciaView.tsx
|-- schemas/
| |-- costoGanancia.schema.ts
|-- services/
| |-- listaPrecio.service.ts
|-- types/
| |-- listaPrecio.types.ts
|-- hooks/
|-- useCostoGanancia.tsMejoras potenciales
- Agregar confirmacion previa antes de ejecucion masiva
- Validar que agrupacion desde <= hasta
- Mostrar resumen de resultados (productos procesados/omitidos)
- Agregar preview de productos afectados antes de ejecutar
- Implementar loading states mas granulares
Preguntas Tecnicas Pendientes
Aclaraciones Requeridas: Hay aspectos tecnicos que requieren validacion. Ver: Preguntas sobre Lista de Precios Costo Ganancia
Referencias
NOTA IMPORTANTE: Esta documentacion fue generada automaticamente analizando el codigo implementado. Validar cambios futuros contra este baseline.