El mismo bloque (~100 lineas) estaba copiado en Picking DESPACHO, Picking PICKING y Recibo. Ahora los tres llaman al mismo metodo. Sin cambios de comportamiento (la referencia de la NC en la transferencia se asigna una vez antes de las lineas en vez de dentro del ciclo de articulos). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
197 lines
12 KiB
Markdown
197 lines
12 KiB
Markdown
# 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`) y se quitaron dos copias
|
||
exactas sin llamadores: `HelperHojaRuta.GetConsolidado` (queda `HelperStock.GetConsolidado`)
|
||
y `HRRepository.UpdateCreateCreditNotes` (queda `CreditNotesRepository`). Sigue pendiente: código
|
||
comentado, `PatchAsyncSBA`, repositorios de compras sin uso
|
||
(`SetCreatePurchaseInvoices` duplicado en `PurchaseOrdersRepository`) y la redundancia de los métodos POST/PATCH del cliente.
|
||
La transferencia automática de stock de la NC (3 copias en Picking x2 y Recibo)
|
||
pasó a un solo método: `Net.Data/ServicesLayer/StockTransfer/TransferenciaAutomaticaNC.Crear`.
|
||
- 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<T>.NombreEstacion`: setter con recursión infinita
|
||
(bomba de tiempo; hoy nada lo asigna).
|
||
- `ConnectionServiceLayer.PatchAsyncSBA<T>`: 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.
|
||
- Si una transferencia automática de stock falla (`TransferenciaAutomaticaNC.Crear`),
|
||
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`.
|