Appearance
Carteras - Documentacion Tecnica Frontend
DOCUMENTACION RETROSPECTIVA - Generada a partir de codigo implementado el 2026-02-09
Modulo: Ventas (vista principal) + CtaCte (componentes React reutilizables) Feature: Carteras (Agrupacion de clientes) Fecha: 2026-02-09
Arquitectura Implementada
Patron: Hibrido - Vista legacy (PHP + vanilla JS) + Componentes React reutilizables
La funcionalidad de Carteras tiene dos capas frontend:
- Vista de ABM (legacy): PHP template + vanilla JS con DataTables y Bootstrap modals
- Componentes de seleccion (React/TypeScript): CarteraSelect y ControlledCarteraSelect para uso en otros formularios
Componentes Implementados
1. Vista Legacy: ABM de Carteras
Pagina principal
Ubicacion: public/view/mod-ventas/cartera.phpScript: public/js/view/mod-ventas/cartera.jsFormulario HTML: public/php/components/mod-venta/forms/cartera.htmlProxy API: public/php/backend/carteras.php
Proposito: Listado, alta y modificacion de carteras de clientes
Dependencias externas:
- jQuery
- DataTables (con plugins: responsive, buttons, export PDF/Excel)
- Bootstrap 4 (modales, layout)
- AdminLTE (sidebar, skin)
cartera.js (Vista principal)
Ubicacion: public/js/view/mod-ventas/cartera.jsTipo: Modulo ES6
Funcionalidad implementada:
Inicializacion de DataTable: Tabla
#tablaCarterascon columnas:Codigo(campoid)Nombre(camponombre)Acciones(boton editar con icono lapiz)- Botones de exportacion: Excel, PDF
Carga de datos: Fetch via
ApiRequest.get('carteras', { tipo: 'cliente' })Alta: Boton
#btn_alta-> abre modal viacreateFormCartera({ onSubmitCallback })Modificacion: Click en boton
#idBtnmodificarCartera-> abre modal viacreateFormCartera({ updateData, onSubmitCallback })con datos de la fila
Imports:
createFormCarteradesde../../components/forms/ventas/cartera.jsApiRequestdesde../../middleware/API.jsreemplazarFiladesde../../util/datatable-methods.js
cartera.js (Formulario)
Ubicacion: public/js/components/forms/ventas/cartera.jsTipo: Modulo ES6, exporta funcion createFormCartera
Parametros de entrada:
{
appendTo?: HTMLElement, // Contenedor opcional (inline form)
updateData?: { id, nombre }, // Datos para edicion
onSubmitCallback: (data) => void // Callback post-submit
}Comportamiento:
- Carga el HTML del formulario desde
cartera.htmlvia fetch - Crea un modal Bootstrap dinamicamente
- Si
updateDatatiene datos, carga los valores en el formulario (modo edicion) - En submit:
- Si
cartera.idexiste:ApiRequest.put('carteras', cartera)(modificacion) - Si
cartera.ides null:ApiRequest.post('carteras', cartera)(alta)
- Si
- Muestra toast de confirmacion
- Ejecuta
onSubmitCallbackcon los datos resultantes - Cierra el modal
Estructura de datos interna:
javascript
let cartera = {
id: null,
nombre: null
}Validaciones frontend:
isValidForm(form): Validacion HTML5 nativa (required)validateTypeen blur del input: Validacion de tipo de datomaxlength="20"en el input HTML
cartera.html (Template del formulario)
Ubicacion: public/php/components/mod-venta/forms/cartera.html
Estructura:
- Modal Bootstrap (fade)
- Titulo: "Formulario de carteras"
- Un solo campo:
Denominacion(input text, maxlength=20, required) - Botones: Cancelar (cierra modal) y Aceptar (submit)
2. Componentes React: Selectores de Cartera
CarteraSelect
Ubicacion: public/ts/ctacte/components/CarteraSelect.tsxTipo: Componente React funcional (mountable component)
Proposito: Selector dropdown de carteras para uso en formularios legacy (vanilla JS) y otros contextos React.
Props:
typescript
interface CarteraSelectProps {
type: 'cliente' | 'proveedor';
label?: string; // Default: 'Cartera'
name?: string; // Default: 'cartera'
value?: string;
onChange?: (cartera: CarteraRecord | null) => void;
onDataLoaded?: (records: CarteraRecord[]) => void;
records?: CarteraRecord[]; // Records pre-cargados (evita fetch)
loading?: boolean;
error?: FieldError;
className?: string;
getApi?: (api: InputFormApi) => void; // API externa (mountable)
}Comportamiento:
- Obtiene carteras via
useCarteraData(type)(o usarecordsproporcionados) - Auto-selecciona el primer registro si no hay valor previo y no esta en RangeSelector
- Expone API via
getApipara control externo (focus, blur, setValue, disable, enable) - Renderiza
FormField+DataSelectcon las opciones de carteras
Componentes internos utilizados:
DataSelect(decore/components)FormField(decore/components/form)
ControlledCarteraSelect
Ubicacion: public/ts/ctacte/components/ControlledCarteraSelect.tsxTipo: Componente React funcional para React Hook Form
Proposito: Version del selector de carteras integrada con React Hook Form para formularios modernos (MUI).
Props:
typescript
interface ControlledCarteraSelectProps<T extends FieldValues> {
name: FieldPath<T>;
control: Control<T>;
label: string;
type: 'cliente' | 'proveedor';
error?: FieldError;
disabled?: boolean;
required?: boolean;
placeholder?: string; // Default: 'Seleccione...'
onValueChange?: (cartera: CarteraRecord | null) => void;
}Comportamiento:
- Usa
Controllerde React Hook Form para controlar el valor - Obtiene carteras via
useCarteraData(type, disabled) - Renderiza un
TextFieldde MUI en modoselectconMenuItems - Muestra spinner de carga cuando los datos estan cargando
- Emite
onValueChangecon el objeto cartera completo al cambiar
Componentes de MUI utilizados:
TextField(modo select)MenuItemCircularProgressBox
Hook Personalizado
useCarteraData
Ubicacion: public/ts/ctacte/hooks/useCarteraData.ts
Parametros:
typescript
function useCarteraData(type: 'cliente' | 'proveedor', skip: boolean = false)Retorno:
typescript
{ records: CarteraRecord[], loading: boolean, error: string | null }Implementacion:
- Usa
useDataSelectdel core (patron generico de carga de datos para selects) - URL base:
'carteras' - Query params:
{ tipo: type } - El parametro
skippermite evitar la carga de datos (cuando ya se proporcionaron records externos o el componente esta deshabilitado)
Tipos TypeScript
CarteraRecord
Ubicacion: public/ts/ctacte/types/carteras.ts
typescript
export const carteraIdField = "id";
export const carteraNameField = "nombre";
export interface CarteraRecord extends RecordType {
id: number;
nombre: string;
}Integracion con Backend
Endpoints Consumidos
| Endpoint | Metodo | Uso | Consumidor |
|---|---|---|---|
carteras?tipo=cliente | GET | Listar carteras de clientes | cartera.js, CarteraSelect, ControlledCarteraSelect |
carteras?tipo=proveedor | GET | Listar carteras de proveedores | CarteraSelect (en contextos de compras) |
carteras | POST | Crear cartera | cartera.js (formulario) |
carteras | PUT | Modificar cartera | cartera.js (formulario) |
Proxy API
Ubicacion: public/php/backend/carteras.php
El proxy frontend actua como intermediario entre el frontend (ApiRequest/axios) y el backend. Realiza:
- Validacion de sesion (
$_SESSION['SD_USER']) - Validacion de datos de entrada (reglas tipo, id, nombre, etc.)
- Reenvio de la solicitud al backend via clase
Requestinterna - Formateo de respuesta
Routing y Navegacion
Vista legacy
- URL:
?loc=mvcc - Breadcrumb: Home > Ventas > Carteras
- Sidebar: Ventas > Bases > Carteras (condicionado a
empres.carteray permisoVENTAS_BASES_CARTERAS) - Sidebar highlight:
idNavMainSideBarBases(abierto) +idMainSideBarCartera(activo)
Componentes React
No tienen routing propio. Se montan dinámicamente donde se necesiten:
CarteraSelect: Montable viamountComponent()en formularios legacyControlledCarteraSelect: Integrado en formularios React con React Hook Form
Contextos de Uso de CarteraSelect
1. Formulario de Clientes (legacy)
Archivo: public/js/components/forms/general/cliente.jsPatron: Mountable component
javascript
import CarteraSelect from '../../../../dist/ctacte/components/CarteraSelect.js';
import { mountComponent } from '../../../../dist/main.js';
const props = {
onChange: (record) => { Cliente.cartera = record; },
type: 'cliente',
className: 'form-group col-md-6',
};
const api = await mountComponent(container, CarteraSelect, props);2. Formulario de Clientes (React - ListaClientesForm)
Archivo: public/ts/ventas/components/ListaClientesForm.tsxPatron: ControlledCarteraSelect dentro de React Hook Form
3. Informes de Saldos (CtaCte)
Archivo: public/ts/ctacte/ (varios contextos) Patron: CarteraSelect como filtro de rango
4. Formulario de Proveedores
Archivo: public/js/view/mod-compras/registro-proveedor.jsPatron: CarteraSelect montado con type='proveedor'
5. Modulo Tesoreria
Archivos: Cheques, boleta de deposito Patron: Referencia a cartera como filtro
Diagrama de Componentes
mermaid
flowchart TD
subgraph "Vista ABM (Legacy)"
A[cartera.php] --> B[cartera.js<br/>Vista DataTable]
B --> C[createFormCartera<br/>Modal Bootstrap]
C --> D[cartera.html<br/>Template]
B --> E[ApiRequest<br/>API.js]
C --> E
E --> F[Proxy PHP<br/>carteras.php]
end
subgraph "Componentes React (ts/ctacte/)"
G[CarteraSelect.tsx] --> H[useCarteraData.ts]
I[ControlledCarteraSelect.tsx] --> H
H --> J[useDataSelect<br/>core hook]
J --> K[axios<br/>api.ts]
K --> F
end
subgraph "Consumidores"
L[cliente.js] -->|mountComponent| G
M[ListaClientesForm.tsx] --> I
N[registro-proveedor.js] -->|mountComponent| G
O[Informes CtaCte] --> G
end
F --> P[Backend<br/>carteras.php]Observaciones Tecnicas
Organizacion de codigo cross-module
Los componentes React de Carteras estan en ts/ctacte/ aunque la vista principal de ABM esta en view/mod-ventas/. Esto se debe a que los componentes selectores se usan predominantemente en contextos de cuenta corriente. Sin embargo, esto crea una dependencia cross-module donde ventas depende de ctacte para sus componentes.
Patron de montaje dual
CarteraSelect implementa el patron MountableComponentProps que permite su uso tanto en contextos React como en vanilla JS via mountComponent(). Expone un InputFormApi con metodos focus, blur, setValue, disable, enable.
Sin migracion a React de la vista principal
La vista de ABM de carteras (listado + formulario) sigue siendo completamente legacy (PHP + vanilla JS + DataTables + Bootstrap modales). Solo los componentes de seleccion han sido migrados a React.
Preguntas Tecnicas Pendientes
Aclaraciones Requeridas: Hay aspectos tecnicos que requieren validacion. Ver: Preguntas sobre Carteras
Referencias
NOTA IMPORTANTE: Esta documentacion fue generada automaticamente analizando el codigo implementado. Validar cambios futuros contra este baseline.