- 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>
163 lines
7.1 KiB
Markdown
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 |
|