# ITCA_API_SAP_WMS (.NET) — proyecto principal API de integración WMS ↔ SAP Business One, **ASP.NET Core 3.1**. Para build/publish/despliegue en IIS ver [`README.md`](./README.md). Esta carpeta (`ITCA_API_SAP_WMS`, antes `backend_octubre`) es **el proyecto vigente**. Antes existía una copia paralela con la funcionalidad nueva portada desde la reescritura Python; se portó aquí y esa copia quedó **archivada en un comprimido (versión antigua)**. ## Versión y control de versiones - **Versión actual: 2.1.8.0** (rama `limpieza-2.1.8.0`; `main` = 2.1.7.0) (`Net.Business.Services.csproj`: `Version`, `AssemblyVersion`, `FileVersion`). Cada versión tiene su commit; al publicar se sube la versión (ver `publicar.ps1`). - **Git**: rama `main`, remoto `origin` = `http://100.68.242.27:30000/george/itca_api_sap_wms.git` (HTTP sin cifrar, red interna; confirmar que el repositorio sea **privado**). Etiqueta `v2.1.7.0` = último estado antes de la limpieza de código. - `appsettings.json` y `appsettings.*.json` están en `.gitignore` (solo se versiona `appsettings.example.json`); las credenciales no están en el historial (verificado con `git log -S`). - Los publish (`dist/`, zip del escritorio) no se versionan. ## Qué se portó desde `ITCA_API_SAP_WMS` (2026-10-05) Detalle técnico en `docs/PORTE_FUNCIONALIDAD_NUEVA.md`, `docs/SOLICITUD_TRANSFERENCIA.md` y `docs/PICKING.md`. 1. **SolicitudTransferencia**: `PATCH /api/SolicitudTransferencia/{docEntry}` y `POST /api/SolicitudTransferencia/{docEntry}/cerrar`. 2. **Picking diurno/nocturno**: campo `Notificacion` (early-return en `PickingRepository.Create` tras `HelperProcesoPiciking.Set`, **solo para `Proceso = "ULTIMA MILLA"`**; DESPACHO/PICKING generan NC sin depender de él) y `POST /api/Picking/HojaRuta/{docEntry}/Cerrar`. 3. **`ConnectionServiceLayer`**: `PatchNoContentAsync` y `PostActionAsync` (métodos nuevos; los existentes no se tocaron). ## Regla Proceso + Notificacion (v2.1.2.0) `Notificacion = "cierre"` se exige **solo si `Proceso = "ULTIMA MILLA"`** (si no, solo actualiza estado en HANA). `DESPACHO` y `PICKING` generan NC y transferencias siempre, sin depender de `Notificacion`. Detalle y tabla en `docs/PICKING.md`. ## Correcciones de la NC en Picking/DESPACHO (v2.1.3.0 y v2.1.4.0) - **v2.1.3.0 — reapertura de factura**: `ConnectionServiceLayer.PostReOpen` trata el `204` sin cuerpo como éxito (antes fallaba al marcar `Exito` sobre `null` y respondía *"La Factura no se puede reabrir"* aunque SAP la reabría). El error de Picking ahora incluye el motivo real de SAP. - **v2.1.4.0 — lotes de la NC en DESPACHO, línea por línea**: si la línea de la factura tiene Entrega de origen (`BaseType = 15`) los lotes salen de la línea de la Entrega (`DeliveryNotes(BaseEntry)`, línea `BaseLine`); si no, de la línea de la factura (`LineNum`). Si los lotes no cubren la cantidad, o no se lee la Entrega, responde un error con línea y artículo. PICKING (estado 13) no cambió (lote nuevo por fecha y hora). Detalle en `docs/PICKING.md`. - **v2.1.5.0 — log del JSON enviado al Service Layer cuando SAP lo rechaza** (cualquier documento, no solo la NC): `ConnectionServiceLayer` llama a `ErrorLogger` (asignado en `Startup` a `Net.Data/HelperData/Log/HelperLogServiceLayer.AddError`) en los fallos de `PostAsync`, `PatchAsyncSBA` y `PatchNoContentAsync`. Guarda en `ITC_WMS_SAP.ITCA_LOG_INTEGRACION`: `ORIGEN = "ServiceLayer"`, `PROCESO = "ServiceLayer Error"`, `NRO_ORDEN` = ruta del recurso (p. ej. `CreditNotes`), `DOCENTRY` = `BaseEntry` de la primera línea del JSON (factura o solicitud base; vacío si no hay), `DOCENTRYSAP`/`DOCNUMSAP` = `0` (SAP rechazó), `TRAMA_ORIGEN` = JSON enviado, `TRAMA_RESPUESTA` = mensaje de SAP. Solo en error. La respuesta de la API al consumidor no cambia y si el log falla no rompe el flujo. No cubre `PostActionAsync` (cuerpo `{}`) ni `PostReOpen`/`PostClose`. Las columnas `PROCESO`, `NRO_ORDEN` y `DOCENTRY` son `VARCHAR(100)`. - **v2.1.6.0 — cantidades**: (1) la NC de PICKING (estado 13) solo incluye líneas con `cantidad facturada − CantidadPedida > 0`, igual que DESPACHO (antes una línea completa generaba una línea de NC con cantidad 0); (2) la transferencia automática de stock (Picking y Recibo) junta los lotes de **todas** las líneas del mismo artículo para el par origen/destino (antes solo tomaba los de la primera línea y la suma no cuadraba con la cantidad). El almacén de la línea de la NC sigue saliendo de la factura, no del `codigoSubAlmacen` del request. - **v2.1.7.0 — NC de Recibo (Devolución, base Solicitud de Devolución)**: (1) los lotes de cada línea eran los del request (`LoteProducto`) **más** los de la distribución (stock HANA o de la factura, o lote de respaldo por fecha/hora), con lo que sumaban el doble y podían incluir un lote vacío; ahora se limpia el lote inicial y quedan solo los de la distribución (el `LoteProducto` del request ya no se usa en la NC); (2) la serie se elige por el **tipo** del documento origen (`U_SYP_MDTO == "03"` → `BC10`, otro → `FC10`); antes se comparaba la serie origen (p. ej. `B005`) con `"03"` y siempre salía `FC10`. Pendiente: validar con contabilidad la serie de boletas, y que Recibo no genera transferencias por almacén destino (nunca llena `U_ITC_ALMDES`). - **v2.1.8.0 — limpieza y comentarios** (rama `limpieza-2.1.8.0`, sin cambios de comportamiento): se quitó código sin uso (`ValidarCertificado`, `Logout`, `CancelAsyncSBA`, `DeleteAsyncSBA`, el `throw` inalcanzable de `PatchAsyncSBA`, `HelperDB`, 11 propiedades de `RepositoryWrapper` sin uso, variables `TotalDetalle_Parcial`/`_Invoice`/`SerieOrigen` y un `if` vacío en `CreateHojaRuta`) y se agregaron comentarios en Picking, Recibo, `ConnectionServiceLayer`, `CreditNotesRepository`, `InvoiceRepository` y `RepositoryWrapper`. Además se unificó `LoginPost()` en `Login()` (eran idénticos; las 4 llamadas a `LoginPost` ahora llaman a `Login`). Sigue pendiente: código comentado, `PatchAsyncSBA` y la redundancia de las transferencias automáticas (3 copias en Picking/Recibo) y de los métodos POST/PATCH del cliente. - Sin probar contra SAP: confirmar con la factura 292410 que SAP devuelve `BaseType`/`BaseEntry` en las líneas y `BatchNumbers` en las de la Entrega. ## Cambios de configuración y correcciones hechas en esta carpeta - **Credenciales y esquema HANA en `appsettings.json`**, sección `Hana` (`server`, `user`, `password`, `schema` opcional), leída por `LocalData.Configure` desde `Startup`. Antes estaban fijas en el código (`LocalData.cs`, `Log/B_Log.cs`). El esquema sale de `Hana:schema` o, si no está, de `SapServiceLayer:company`; **si falta la sección `Hana` o el esquema, la app no arranca** (error claro). Ya no hay `DB_NAME` fijo. - **Precio promedio solo en entradas** (`TipoMovimiento "01"`) en `InventarioRepository.Create` (los dos chequeos: `SubAlmacen` y `Almacen`). Si el artículo no tiene stock, se conserva el `PrecioPromedio` del request en vez de abortar con *"No existe stock disponible para el articulo X"* (ese error bloqueaba ingresos de artículos sin stock previo). En salidas ya no se busca el promedio: `PriceAfterVAT` lleva el precio del request. El chequeo de stock de la rama de **salida** de `PickingRepository` (~línea 363) no se tocó. - **Lote de 100 líneas** (`InventarioRepository.Create`): `var Inventario = entidad` reutilizaba el mismo objeto, y con más de 100 líneas se generaban N documentos iguales con el último bloque. Ahora se crea una copia por bloque y la rama de salida lee `entidad_inventario.Detalle`. - **SQL injection**: parametrizadas las consultas de `HelperProcesoPiciking`, `HelperStock`, `HelperInventario`, `HelperInvoice`, `HelperCorrelativo`, `HelperHojaRuta` y `HelperProcesoPermitido` (`?` + `HanaParameter`). El esquema sigue interpolado (viene de configuración, no del request). - `ITCA_API_SAP_WMS.xml` ahora se genera también en Release (sin eso Swagger revienta con `FileNotFoundException` en un `publish -c Release`). ## Funcionalidad propia de esta carpeta (no existe en la copia antigua) Hoja de Ruta (`HojaRutaController`, `HRRepository`, `GlobalDataRepository`), reapertura de facturas (`InvoiceRepository.ReOpen`, `PostReOpen`), notas de crédito con documentos de referencia, cierre automático de la solicitud de traslado en `Transferencia` (`PostClose`), `Latitud`/`Longitud` y reproceso en Picking, columna `HORA` en `B_Log`. Lo que **no** se trajo: `Chatbots` y `MessageController` (solo existen en la copia archivada). ## Sin verificar - **Nada se probó contra SAP/HANA reales.** Solo se verificó que compila (0 errores) y que el publish se genera. - La sintaxis `CALL "esquema"."proc"(?, ?)` con parámetros no está probada con el driver HANA 2.1; si falla con un error de parámetro, mirar primero ahí. - Para probar el lote de 100: un inventario de >100 líneas (p. ej. 250) debe generar 3 documentos (100/100/50) sin repetir ni perder líneas, tanto en entradas como en salidas. ## Bugs conocidos, sin corregir - `BE_ResultadoTransaccion.NombreEstacion`: setter con recursión infinita (bomba de tiempo; hoy nada lo asigna). - `ConnectionServiceLayer.PatchAsyncSBA`: con un `204` real devuelve `null` sin marcar éxito. - El cliente HTTP `bypass-ssl-validation` acepta cualquier certificado TLS hacia el Service Layer (se quitó el método `ValidarCertificado`, que no se usaba). - `appsettings.json` (fuera de git, en `.gitignore`) contiene credenciales reales en texto plano (SAP Service Layer, **HANA `B1ADMIN`**, semilla JWT). Rotar la contraseña de `B1ADMIN` (estuvo en el código fuente) y evaluar un usuario HANA de mínimos permisos. - Los logs (`B_Log` y `HelperLogServiceLayer`) escriben en el esquema fijo `ITC_WMS_SAP` (`ITCA_LOG_INTEGRACION`), no en `LocalData.Schema`; si la tabla está en otro esquema el `INSERT` falla. `B_Log.Add` no tiene `try/catch`, así que un fallo del log puede devolver 500 tras haber creado el documento en SAP. - En Picking y Recibo, si la transferencia automática de stock falla, el `if` de error está vacío: el fallo se ignora (la NC ya está creada) y no se informa al consumidor. ## Despliegue Sitio IIS previsto: **`/integracion`** (antes `/integracion_wms`). Publicar con el comando del README **sin pisar** el `appsettings.json` del servidor; agregar a ese archivo la sección `Hana` y revisar `SapServiceLayer:company` (determina contra qué base lee y escribe). El `web.config` generado por `dotnet publish` usa `processPath=".\ITCA_API_SAP_WMS.exe"`; el del código fuente apunta a `bin\Debug\...` (solo para sitios que corren desde el código compilado). ## Pendiente - Probar en QA: endpoints nuevos (SolicitudTransferencia, `Notificacion`, `HojaRuta/Cerrar`), un ingreso sin stock previo, el lote de 100 y las consultas parametrizadas. - Verificar que existan en el esquema del sitio los procedimientos `ITCA_*` y las tablas `@ITCA_PROWMS`, `@SYP_MOTIVOS`, `@SYP_NUMDOC`. - Decidir si se corrigen los bugs de la lista de arriba. - Validar con contabilidad la serie de NC de boletas (`BC10`) en Recibo y si ya hay NC de boletas emitidas con `FC10` antes de la 2.1.7.0. - Recibo (Devolución) no genera transferencias por almacén destino: nunca llena `U_ITC_ALMDES` en las líneas de la NC. - Confirmar en QA el log de errores del Service Layer (provocar un rechazo y ver la fila con `PROCESO = 'ServiceLayer Error'`) y el esquema de la tabla de log en cada servidor. - Confirmar el repositorio remoto como privado; hacer la limpieza de código en una rama aparte (2.1.8.0) partiendo de la etiqueta `v2.1.7.0`.