Files
mini-erp/mini-frontend/docs/flujo-articulos.md
T
GeorgeandClaude Sonnet 5 f58f4292c3 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>
2026-09-28 14:28:29 -05:00

163 lines
7.1 KiB
Markdown

# Flujo de Procesamiento — Datos Maestros de Artículos
## Arquitectura General
```mermaid
graph TB
subgraph "Frontend React (sap-frontend)"
RT[Router App.tsx]
LIST[ItemsList.tsx]
LIST_TMPL[ListViewTemplate.tsx]
VISTA[Items.tsx]
FORM[ItemForm.tsx]
UI_FF[FormattedField.tsx]
UI_SEL[SelectField.tsx]
UI_TABLE[DenseTable.tsx]
API[api.ts]
ENUMS[enums.ts]
TYPES[types/sapItems.ts]
end
subgraph "Backend FastAPI (mini-backend)"
ROUTER[routers/items.py<br/>make_crud_router]
CORE[core/crud_router.py]
SAPCORE[core/sap.py<br/>forward_to_sapb1]
end
subgraph "SAP Business One"
SL[Service Layer<br/>Items / ItemGroups]
end
RT --> LIST
RT --> VISTA
LIST --> LIST_TMPL
LIST_TMPL --> UI_TABLE
LIST_TMPL --> API
VISTA --> FORM
FORM --> UI_FF
FORM --> UI_SEL
FORM --> API
FORM --> ENUMS
FORM --> TYPES
API -->|GET/POST/PATCH| ROUTER
ROUTER --> CORE
CORE --> SAPCORE
SAPCORE -->|B1SESSION| SL
```
**Diferencia clave respecto al flujo de Lotes:** `ItemForm.tsx` no hace mapeo de nombres SAP→amigable (no existe un `mapSapToFriendly`). El estado del formulario (`SapItem`, en `types/sapItems.ts`) usa directamente los nombres de campo de SAP (`ItemCode`, `ItemName`, `ItemsGroupCode`, etc.), tanto para mostrar como para enviar al backend. Tampoco hay tabla de mapeo de nombres en esta sección por ese motivo.
En el backend, `routers/items.py` no tiene lógica propia: es una instancia de la factory genérica `make_crud_router("Items", key_field="ItemCode", key_quoted=True)` definida en `core/crud_router.py` (ver `mini-backend/docs/architecture.md`), que arma las cuatro rutas CRUD y reenvía a SAP vía `core/sap.py`.
## Flujo Vista de Lista → Editar/Crear Artículo
```mermaid
sequenceDiagram
actor User as Usuario
participant Router as App.tsx
participant ListView as ItemsList
participant LVT as ListViewTemplate
participant DTable as DenseTable
participant DetailView as Items
participant Form as ItemForm
participant API as api.ts
participant Backend as backend items.py
participant SAP as SAP Service Layer
User->>Router: /inventario/articulos
Router->>ListView: render
ListView->>API: GET /api/ItemGroups (para mapear ItemsGroupCode → nombre en la columna "Grupo")
ListView->>LVT: <ListViewTemplate endpoint="Items" baseFilter="AssetItem eq 'tNO'" .../>
LVT->>API: GET /api/Items?skip=0&top=50&fields=ItemCode,ItemName,...
API->>Backend: fetch con X-Session-Token
Backend->>SAP: GET Items (con B1SESSION)
SAP-->>Backend: JSON con datos
Backend-->>API: JSON response
API-->>LVT: json.value[]
LVT->>DTable: render rows
DTable-->>User: tabla con artículos (filtros por Grupo y Clase de artículo)
User->>DTable: clic en editar (ItemCode "A0001")
DTable->>Router: navigate("/inventario/articulos/mantenimiento?code=A0001")
Router->>DetailView: render con searchParams.code
DetailView->>Form: <ItemForm itemCode="A0001" backPath="/inventario/articulos" />
Form->>API: GET /api/ItemGroups (para poblar el SelectField de grupo)
Form->>API: GET /api/Items/A0001
API->>Backend: fetch
Backend->>SAP: GET Items('A0001')
SAP-->>Backend: {ItemCode, ItemName, ItemsGroupCode, ItemType, ...}
Backend-->>API: JSON raw SAP
API-->>Form: data
Form->>Form: setItem(data) (sin mapeo de nombres)
Form-->>User: formulario con valores cargados
User->>Form: edita campos y clic "Actualizar Artículo"
Form->>API: PATCH /api/Items/A0001
Note over Form,API: body: {ItemName, BarCode, ItemsGroupCode, ItemType, ...}
API->>Backend: fetch PATCH
Backend->>SAP: PATCH Items('A0001')
SAP-->>Backend: 204 No Content
Backend-->>API: 204
API-->>Form: ok
Form-->>User: "Artículo actualizado exitosamente"
Note over User,SAP: Si itemCode no viene en la URL (alta), el botón dice<br/>"Crear Artículo" y el submit hace POST /api/Items en vez de PATCH.
```
## Árbol de Componentes
```
App.tsx (BrowserRouter)
└── / (ProtectedRoute → MainLayout)
└── /inventario
├── /articulos
│ └── ItemsList.tsx
│ └── ListViewTemplate.tsx
│ ├── SearchInput.tsx
│ ├── PrimaryButton.tsx
│ ├── DenseTable.tsx
│ │ └── formatValue() [formatters.ts]
│ └── PaginationBar.tsx
└── /articulos/mantenimiento
└── Items.tsx
└── ItemForm.tsx
├── FormattedField.tsx (x6)
└── SelectField.tsx (x3: ItemsGroupCode, ItemType, CostAccountingMethod)
```
## 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) |
| `ItemName` | input text | FormattedField | obligatorio |
| `BarCode` | input text | FormattedField | |
| `ItemsGroupCode` | select | SelectField | opciones cargadas desde `GET /api/ItemGroups` |
| `ItemType` | select | SelectField | opciones estáticas `ITEM_TYPE` (`utils/enums.ts`) |
| `CostAccountingMethod` | select | SelectField | opciones estáticas `GL_METHOD` (`utils/enums.ts`) |
| `SalesUnit` | input text | FormattedField | |
| `PurchaseUnit` | input text | FormattedField | |
| `InventoryUOM` | input text | FormattedField | |
| `AvgStdPrice` | currency, solo lectura | FormattedField (`mode="display"`) | |
| `PurchaseItem`, `InventoryItem`, `ManageSerialNumbers`, `ManageBatchNumbers`, `Valid`, `Frozen` | checkbox | input nativo | mapean a `"tYES"`/`"tNO"` vía `toCheck`/`fromCheck` |
## Archivos Clave
| Archivo | Ruta | Propósito |
|---|---|---|
| `Items.tsx` | `src/views/inventario/` | Vista detalle, extrae `code` de la URL y renderiza `ItemForm` (sirve tanto para alta como edición) |
| `ItemForm.tsx` | `src/components/` | Formulario alta/edición, fetch + POST/PATCH sin mapeo de nombres |
| `ItemsList.tsx` | `src/views/inventario/` | Lista con filtros por grupo de artículos y clase de artículo, columnas con formato de moneda |
| `SelectField.tsx` | `src/components/ui/` | Select reutilizable |
| `FormattedField.tsx` | `src/components/ui/` | Campo display/input con formato |
| `ListViewTemplate.tsx` | `src/components/ui/` | Template genérico de listado con paginación/búsqueda/filtros |
| `api.ts` | `src/utils/` | Cliente HTTP con sesión, token, timeout |
| `enums.ts` | `src/utils/` | Opciones estáticas `ITEM_TYPE`, `GL_METHOD` |
| `sapItems.ts` | `src/types/` | Interfaz TypeScript `SapItem` |
| `items.py` | `mini-backend/routers/` | Instancia de `make_crud_router` para `Items` (GET lista, GET por código, POST, PATCH) |
| `crud_router.py` | `mini-backend/core/` | Factory genérica de routers CRUD reutilizada por `items.py` y otros routers |
| `sap.py` | `mini-backend/core/` | Proxy universal a SAP Service Layer |