# 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
make_crud_router] CORE[core/crud_router.py] SAPCORE[core/sap.py
forward_to_sapb1] end subgraph "SAP Business One" SL[Service Layer
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: 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: 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
"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 |