Base para el flujo de ramas por cliente. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
4.7 KiB
4.7 KiB
Flujo de Proxy SAP
Función Central: forward_to_sapb1
Todas las operaciones CRUD pasan por esta función en core/sap.py, que actúa como proxy hacia SAP Service Layer.
flowchart TD
START([Inicio]) --> INPUT["method, endpoint_path,\njson_data, params, headers"]
INPUT --> BUILD["Construye URL:\nSAPB1_SL_URL / endpoint_path"]
BUILD --> HEADERS["Adjunta headers:\nCookie: B1SESSION=...\nContent-Type: application/json"]
HEADERS --> SEND[Envía request a SAP]
SEND --> CHECK{Respuesta}
CHECK -->|2xx| SUCCESS[Retorna Response al router]
CHECK -->|401| REFRESH["Force refresh:\nensure_sap_session()"]
CHECK -->|Timeout / Error| FAIL[ConnectionError]
REFRESH --> RETRY{Es reintento?}
RETRY -->|No| SEND2["Reintenta request\ncon nueva sesión"]
RETRY -->|Sí| ERROR["Extrae error.message.value\nde SAP y lanza HTTPException"]
SEND2 --> CHECK2{Respuesta}
CHECK2 -->|2xx| SUCCESS
CHECK2 -->|4xx/5xx| ERROR
SUCCESS --> END([Fin])
FAIL --> END
ERROR --> END
style ERROR fill:#f96,stroke:#a33
Diagrama de Secuencia — Operación CRUD Típica
Ejemplo con GET /api/Items:
sequenceDiagram
participant F as Frontend
participant MW as Middleware
participant R as router/items.py
participant C as core/sap.py
participant SAP as SAP Service Layer
F->>MW: GET /api/Items?$skip=0&$top=20\nX-Session-Token: [token]
MW->>MW: Valida sesión
MW->>R: request.state.emp_id = "123"
R->>C: forward_to_sapb1(\n GET, "Items?$skip=0&$top=20&$inlinecount=allpages")
C->>SAP: GET /b1s/v1/Items?$skip=0&$top=20\nCookie: B1SESSION=abc123
SAP-->>C: 200 - value: [...], odata.count: 150
C-->>R: Response
R-->>F: 200 - data: [...], total: 150
Re-autenticación Automática ante 401
Cuando SAP rechaza la sesión actual (401), el sistema renueva automáticamente la sesión de SAP y reintenta:
sequenceDiagram
participant R as Router
participant C as core/sap.py
participant SAP as SAP Service Layer
R->>C: forward_to_sapb1(GET, "Items?...")
C->>SAP: GET /b1s/v1/Items?...\nCookie: B1SESSION=abc123
SAP-->>C: 401 Unauthorized
Note over C: Sesión SAP expirada\n→ Re-autentica y reintenta
C->>SAP: POST /Login\nUserName: manager, Password: ..., CompanyDB: ...
SAP-->>C: 200 SessionId: xyz789
C->>C: Actualiza sap_session_store
C->>SAP: GET /b1s/v1/Items?...\nCookie: B1SESSION=xyz789
SAP-->>C: 200 - value: [...]
C-->>R: Response 200
Note over R,C: Si el reintento también falla (4xx/5xx)\n→ se extrae error.message.value\n→ se lanza HTTPException
Parámetros OData y Headers SAP Soportados
Query Parameters (OData)
| Parámetro | Uso | Ejemplo |
|---|---|---|
$skip |
Paginación — desplazamiento | $skip=20 |
$top |
Paginación — límite por página | $top=20 |
$select |
Selección de campos | $select=ItemCode,ItemName |
$filter |
Filtrado | $filter=ItemCode eq 'A001' |
$orderby |
Ordenamiento | $orderby=ItemCode asc |
$inlinecount |
Contar registros totales | $inlinecount=allpages |
Headers SAP
| Header | Función |
|---|---|
B1S-PageSize |
Tamaño de página personalizado |
B1S-CaseInsensitive |
Búsqueda sin distinción mayúsc/minúscula |
B1S-ReplaceCollectionsOnPatch |
Reemplazar colecciones completas en PATCH |
Manejo de Errores
| Situación | Comportamiento |
|---|---|
| SAP devuelve 2xx | Retorna Response al router (200 body, 201 body, 204 vacío) |
| SAP devuelve 401 | Re-autentica automáticamente y reintenta 1 vez |
| SAP devuelve 4xx/5xx | Extrae error.message.value y lanza HTTPException(status_code, detail) |
| Timeout de conexión | Lanza ConnectionError |
| Error de red | Lanza ConnectionError |
| Reintento también falla | Lanza HTTPException con el mensaje de error SAP |
| SAP no disponible | HTTPException(500) |