Backport de mejoras genéricas de frontend (desde cliente/tagumedica)
- Nuevo Icon.tsx (reemplaza emojis en toda la app), FieldTooltip, ConfirmModal, PageLoader, SecondaryButton, hook useSapCatalog, utils/errors (getErrorMessage). - App.tsx: code-splitting con lazy()+Suspense+PageLoader para todas las rutas. - MainLayout.tsx: menú usa Icon.tsx en vez de emojis. - FormattedField/SelectField: soporte de dbField+tooltip, multiline. - DenseTable/FilterBar/ListViewTemplate: onClear, mejoras varias. - PrimaryButton: variante de tamaño sm/md. - Renombres *View.tsx para uniformar el naming de vistas de detalle/mantenimiento (Dashboard, Items, BatchNumberDetails, Customers, Suppliers, Invoices, Orders, PurchaseOrders, PurchaseInvoices) y SapLogin -> SapLoginForm. - BatchNumberDetailsList: filtros y columna de descripción de artículo. - Configs de reportes e iconos de módulos actualizados a Icon.tsx. - Ajustes de paleta en los 4 temas CSS. - Docs actualizadas. Se excluyó explícitamente del backport (queda solo en cliente/tagumedica, no es reusable sin adaptar a los UDFs propios de cada cliente): - Vistas InmovilizarLotesView, LiberarLotesView, ConfirmarLiberacionLoteView y sus rutas/ítems de menú. - types/sapInventoryLock.ts (contrato con los UDFs U_SIS_MOVINV/U_EXX_TIPOOPER/U_SIS_TIPDESP/U_SIS_MOTALM de Tagumedica). - En BatchForm.tsx: los 3 campos U_SIS_MOTEST/U_SIS_COMEST/U_SIS_ACCTOM (Motivo/Comentario/Acción), manteniendo el resto de mejoras genéricas del archivo y reactivando el campo estándar "Detalles/Observaciones" que en tagumedica había quedado comentado sin justificación genérica. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
fef21898f9
commit
f58f4292c3
55 files changed
+1014
-356
No files matched your search
@@ -128,6 +128,8 @@ App.tsx (BrowserRouter)
|
||||
|
||||
## Campos del Formulario (nombres SAP, sin mapeo)
|
||||
|
||||
El label de cada campo muestra el nombre técnico SAP en un tooltip (ícono ⓘ, prop `dbField`) en vez de mostrarlo dentro del propio texto del label — ver `FieldTooltip.tsx` y la misma convención en `flujo-lotes.md`.
|
||||
|
||||
| Campo SAP | Tipo | Componente | Notas |
|
||||
|---|---|---|---|
|
||||
| `ItemCode` | input text | FormattedField | obligatorio, deshabilitado implícitamente en edición (se usa como key de URL) |
|
||||
|
||||
@@ -69,12 +69,30 @@ Cada vista de mantenimiento (`Orders.tsx`, `Invoices.tsx`, `PurchaseOrders.tsx`,
|
||||
| `titulo` | Encabezado visible del formulario | `"Factura de Ventas (OINV)"` |
|
||||
| `headerExtraFields` | Campos de cabecera exclusivos de ese documento | Facturas: `FolioPrefixString`, `FolioNumber`, `GroupNum` |
|
||||
| `lineColumns` | Columnas de la grilla de líneas, cada una con un `show(doc)` opcional para ocultar/mostrar según `DocType` | Compras oculta `ItemCode`/`Almacén` si `DocType` es de servicio |
|
||||
| `copyFromSources` | Documentos origen habilitados para el botón "📋 Copiar de" | Facturas de Venta: Orden de Venta y Entrega; Facturas de Proveedor: Orden de Compra |
|
||||
| `copyFromSources` | Documentos origen habilitados para el botón "Copiar de" (ícono de portapapeles) | Facturas de Venta: Orden de Venta y Entrega; Facturas de Proveedor: Orden de Compra |
|
||||
| `retencionConfig` / `detraccionConfig` | Solo presentes en `PurchaseInvoices.tsx` — habilitan los bloques de Retención (3%/6%) y Detracción (SUNAT) en el resumen de totales | No se pasan en Órdenes ni en Facturas de Venta |
|
||||
| `onBuscarSocio`, `onBuscarArticulos`, `onCellSearch` | Callbacks que abren los `ModalSearchTemplate` de Socios, Artículos, Almacén y Código de Impuesto | Cada vista instancia sus propios modales y decide qué endpoint/filtro usar |
|
||||
|
||||
El cálculo de totales (subtotal, impuesto 18% fijo, retención, detracción, total general) vive dentro del propio `MarketingDocumentForm`, no en las vistas.
|
||||
|
||||
Los íconos de acción (búsqueda, copiar de, catálogo, eliminar línea) son SVG inline definidos en `src/components/ui/Icon.tsx` — no hay emojis ni dependencias externas de iconografía en el proyecto.
|
||||
|
||||
### Campo técnico en tooltip, no en el label
|
||||
|
||||
Cada `CampoConfig`/`HeaderExtraFieldConfig` de `genericHeaderFields` acepta un `dbField` (= su propio `name`, ya que ambos son literalmente el nombre del campo en `MarketingDocument`) que `FormattedField`/`SelectField` muestran como un ícono ⓘ junto al label; al pasar el mouse aparece el nombre técnico SAP (ej. `DocEntry`, `CardCode`). Antes el label concatenaba ambos textos ("Documento (DocEntry)"), lo que a veces partía el campo en dos líneas y deformaba la grilla — ver `FieldTooltip.tsx`.
|
||||
|
||||
### Campos de solo lectura (`readOnly` / `readOnlyOnUpdate`)
|
||||
|
||||
`CampoConfig` soporta dos flags que `MarketingDocumentForm` traduce a `mode="display"` (o `disabled` en los `SelectField`):
|
||||
|
||||
| Campo | Flag | Comportamiento |
|
||||
|---|---|---|
|
||||
| `DocEntry` | `readOnly: true` | Nunca editable (ni al crear ni al actualizar) — lo asigna SAP |
|
||||
| `DocNum` | `readOnlyOnUpdate: true` | Editable al crear, bloqueado al actualizar |
|
||||
| `CardCode` | `readOnlyOnUpdate: true` | Editable al crear, bloqueado al actualizar; además oculta el botón de búsqueda de socio cuando está bloqueado |
|
||||
|
||||
`readOnlyOnUpdate` se evalúa contra `isEditMode` (`!!docEntry`), definido dentro del propio `MarketingDocumentForm`.
|
||||
|
||||
## Flujo: Crear una Factura de Venta copiando una Orden
|
||||
|
||||
```mermaid
|
||||
@@ -96,11 +114,11 @@ sequenceDiagram
|
||||
Backend->>SAP: GET Currencies
|
||||
SAP-->>Form: lista de monedas
|
||||
|
||||
User->>Form: busca y selecciona Cliente (🔍)
|
||||
User->>Form: busca y selecciona Cliente (ícono de lupa)
|
||||
Form->>View: onBuscarSocio() abre ModalSearchTemplate(BusinessPartners)
|
||||
View-->>Form: setDoc({CardCode, CardName})
|
||||
|
||||
User->>Form: clic "📋 Copiar de" → "Orden de Venta"
|
||||
User->>Form: clic "Copiar de" → "Orden de Venta"
|
||||
Form->>Copy: <CopyFromModal source={Orden} cardCode docType />
|
||||
Copy->>API: GET /api/Orders?filtro por CardCode/BaseType
|
||||
API->>Backend: fetch
|
||||
@@ -143,11 +161,16 @@ App.tsx (BrowserRouter)
|
||||
└── /mantenimiento → PurchaseInvoices.tsx → MarketingDocumentForm (+ Retención/Detracción)
|
||||
|
||||
MarketingDocumentForm.tsx
|
||||
├── FormattedField.tsx / SelectField.tsx (cabecera)
|
||||
├── FormattedField.tsx / SelectField.tsx (cabecera, con FieldTooltip por campo)
|
||||
├── PrimaryButton.tsx / SecondaryButton.tsx (submit / cancelar)
|
||||
├── Icon.tsx (íconos SVG: buscar, copiar, catálogo, eliminar)
|
||||
├── PageLoader.tsx ("Cargando documento..." mientras hace fetch)
|
||||
├── CopyFromModal.tsx (botón "Copiar de")
|
||||
└── (por vista) ModalSearchTemplate.tsx ×4 (Socios, Artículos, Almacén, Código de Impuesto)
|
||||
```
|
||||
|
||||
Cada vista de mantenimiento (`Orders`, `Invoices`, `PurchaseOrders`, `PurchaseInvoices`) se carga con `React.lazy()` desde `App.tsx`: el JS de un módulo no se descarga hasta que el usuario navega a él (ver `docs/index.md`).
|
||||
|
||||
## Archivos Clave
|
||||
|
||||
| Archivo | Ruta | Propósito |
|
||||
@@ -158,8 +181,11 @@ MarketingDocumentForm.tsx
|
||||
| `OrdersList.tsx`, `InvoicesList.tsx`, `PurchaseOrdersList.tsx`, `PurchaseInvoicesList.tsx` | `src/views/ventas/`, `src/views/compras/` | Listados vía `ListViewTemplate`, con `StatusBadge` por estado del documento |
|
||||
| `CopyFromModal.tsx` | `src/components/ui/` | Modal para copiar líneas desde un documento base (Orden→Entrega→Factura) |
|
||||
| `ModalSearchTemplate.tsx` | `src/components/ui/` | Modal de búsqueda genérico reutilizado para Socios, Artículos, Almacenes, Códigos de Impuesto |
|
||||
| `sapMarketing.ts` | `src/types/` | `MarketingDocument`, `DocumentLine`, `DocumentConfigProps`, `CopyFromSource`, `LineColumnConfig` |
|
||||
| `sapMarketing.ts` | `src/types/` | `MarketingDocument`, `DocumentLine`, `DocumentConfigProps`, `CopyFromSource`, `LineColumnConfig` (`key`/`name` tipados como `keyof DocumentLine`/`keyof MarketingDocument`, no `string` suelto) |
|
||||
| `sunat.ts` | `src/utils/` | `DETRACCION_CODIGOS` (porcentajes SUNAT usados en Facturas de Proveedor) |
|
||||
| `Icon.tsx` | `src/components/ui/` | Registro de íconos SVG inline (reemplaza los emojis que se usaban antes en botones y menú) |
|
||||
| `FieldTooltip.tsx` | `src/components/ui/` | Ícono ⓘ con el nombre técnico SAP del campo, usado por `FormattedField`/`SelectField` |
|
||||
| `errors.ts` | `src/utils/` | `getErrorMessage(err, fallback)` — evita `catch (err: any)` en cada formulario |
|
||||
| `sales.py` / `purchases.py` | `mini-backend/routers/` | Endpoints REST que proxean a SAP Service Layer |
|
||||
|
||||
## Hallazgos (código tal cual está hoy, sin corregir)
|
||||
|
||||
@@ -124,6 +124,8 @@ App.tsx (BrowserRouter)
|
||||
|
||||
## Mapeo de Nombres SAP → Friendly
|
||||
|
||||
El label visible ya no concatena el nombre técnico (antes: "Estado de Aprobación (U_SIS_ESTLOT)", partiéndose en 2 líneas y deformando la grilla). Ahora el label muestra solo el nombre amigable y el campo SAP aparece en un tooltip (ícono ⓘ) vía el prop `dbField` de `FormattedField`/`SelectField` — ver `FieldTooltip.tsx`.
|
||||
|
||||
| Campo SAP | Nombre Amigable | Tipo | Componente |
|
||||
|---|---|---|---|
|
||||
| `Batch` | `Batch` | display | FormattedField |
|
||||
|
||||
@@ -143,7 +143,7 @@ App.tsx (BrowserRouter)
|
||||
|
||||
## Campos del Formulario
|
||||
|
||||
A diferencia del módulo de Lotes, acá **no hay mapeo de nombres SAP → amigable**: el formulario usa los nombres de campo de SAP directamente como `name` de cada input (`CardCode`, `CardName`, `FederalTaxID`, `Phone1`, `EmailAddress`).
|
||||
A diferencia del módulo de Lotes, acá **no hay mapeo de nombres SAP → amigable**: el formulario usa los nombres de campo de SAP directamente como `name` de cada input (`CardCode`, `CardName`, `FederalTaxID`, `Phone1`, `EmailAddress`). El label visible sí es un texto amigable en español; el nombre técnico SAP se muestra en un tooltip (ícono ⓘ, componente `FieldTooltip.tsx`) en vez de ir concatenado al label.
|
||||
|
||||
| Campo SAP | Pestaña | Tipo | Notas |
|
||||
| ------------------------- | ------------ | ------------------------------ | ------------------------------------------------------------- |
|
||||
|
||||
@@ -18,3 +18,14 @@ SPA en React 19 + TypeScript + Vite + Tailwind CSS + React Router. Consume la AP
|
||||
- Todos los documentos siguen el mismo formato: diagrama de arquitectura (mermaid), diagrama de secuencia del flujo principal, árbol de componentes y tabla de "Archivos Clave".
|
||||
- Ver también `mini-erp/CLAUDE.md` (raíz del repo) para la arquitectura general del monorepo (`mini-backend` + `mini-frontend`) y el flujo de trabajo por cliente.
|
||||
- Ver `mini-backend/docs/` para la documentación del backend (API, autenticación, proxy SAP, logging).
|
||||
|
||||
## Rendimiento: carga por ruta (code splitting)
|
||||
|
||||
`App.tsx` no importa las vistas de forma directa: cada una se carga con `React.lazy()`, agrupadas por módulo (Inventario, Socios, Ventas, Compras, Informes), y `<Suspense fallback={<PageLoader />}>` envuelve todo el árbol de rutas. Así el usuario solo descarga el JS de la pantalla que realmente visita, en vez de un único bundle con las 20+ vistas del ERP. `SapLogin` y `MainLayout` (el "shell" de la app) se mantienen fuera de esto porque se necesitan en casi toda visita.
|
||||
|
||||
## Componentes UI compartidos relevantes
|
||||
|
||||
- `Icon.tsx` (`src/components/ui/`) — registro de íconos SVG inline (buscar, copiar, editar, eliminar, etc.). No hay emojis ni librerías de iconografía externas en el proyecto.
|
||||
- `FieldTooltip.tsx` — ícono ⓘ junto al label de un campo, muestra el nombre técnico SAP (prop `dbField` de `FormattedField`/`SelectField`) sin concatenarlo al texto del label.
|
||||
- `PageLoader.tsx` — estado de carga a pantalla completa, reutilizado como fallback de `Suspense` y en los formularios de detalle mientras traen sus datos.
|
||||
- `PrimaryButton.tsx` / `SecondaryButton.tsx` — botones de acción con dos tamaños (`size="sm"` para barras de herramientas, `size="md"` para pies de formulario).
|
||||
Reference in new issue
Block a user