primer commit
This commit is contained in:
1 parent
ab3c613165
commit
b2fb4e2d0a
18 files changed
+1291
-277
No files matched your search
@@ -0,0 +1,160 @@
|
||||
# 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)
|
||||
|
||||
| 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 |
|
||||
Reference in new issue
Block a user