# hana_manager.py — SAP HANA directo Acceso de solo lectura a SAP HANA con `hdbcli`. Se usa para dos cosas: 1. **Fallback de `sapb1_manager.get_delivery_notes`**: ubicar una guía de remisión cuando el Service Layer no la encuentra. 2. **Valor referencial por guía**: ejecutar `Sp_ObtenerValorReferencial` (lo consume `draft_sap.obtener_valor_referencial_sap`). ## Estructura ``` hana_manager.py ├── CONFIG (.env): HANA_SERVER, HANA_PORT (30015), HANA_USER, HANA_PASSWORD, HANA_SCHEMA ├── get_connection() → conexión | None ├── get_delivery(tipo, serie, numero) → list[dict] │ ├── _query_delivery_table(conn, "ODLN", ...) (Entregas) │ └── _query_delivery_table(conn, "OWTR", ...) (Traslados; solo si ODLN no devolvió nada) └── obtener_valor_referencial(serie, numero) → float ``` ## `get_delivery(tipo, serie, numero)` ```mermaid flowchart TD A[get_delivery] --> B{get_connection OK?} B -- No --> Z["return []"] B -- Sí --> C["Consultar ODLN"] C --> D{¿Hay resultados?} D -- Sí --> R["return resultados (Tabla = 'ODLN')"] D -- No --> E["Consultar OWTR"] E --> R2["return resultados (Tabla = 'OWTR') o []"] ``` Filtro aplicado en ambas tablas: | Campo SAP | Valor | |-----------|-------| | `CANCELED` | `'N'` | | `U_BPP_MDTD` | `tipo` (código SUNAT: `09`, `31`) | | `U_BPP_MDSD` | `serie` | | `U_BPP_MDCD` | `LIKE '%numero%'` | Cada registro devuelto trae `DocEntry`, `DocNum`, `CardCode`, `CardName` y `Tabla`. El campo `Tabla` le dice a `sapb1_manager` qué endpoint del Service Layer usar después: `DeliveryNotes` (ODLN) o `StockTransfers` (OWTR, que además requiere resolver la orden de venta por `U_IDC_NUMOV`). ## `obtener_valor_referencial(serie, numero)` Ejecuta `CALL ""."Sp_ObtenerValorReferencial"(serie, numero)` y devuelve la columna `ValorReferencial` del primer registro. Retorna `0.0` si no hay filas, si el valor es nulo o si ocurre un error. ## Comportamiento ante errores Ninguna función lanza excepciones: todas registran un `ERROR` en el log y devuelven un valor neutro (`None` en `get_connection`, `[]` en `get_delivery`, `0.0` en `obtener_valor_referencial`). Por eso las credenciales de HANA son obligatorias en `config_validator`: sin ellas el pipeline seguiría ejecutándose con valores referenciales en 0 sin detenerse. ## Notas - Cada llamada abre y cierra su propia conexión (no hay pool). - El número se busca con `LIKE '%numero%'`: es una coincidencia parcial, así que un número corto podría coincidir con más de un documento de la misma serie. - El esquema se interpola en el SQL desde `HANA_SCHEMA` (`.env`); los valores de búsqueda sí van como parámetros (`?`).