15 KiB
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.
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.11.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 (verpublicar.ps1). - Git: rama
main, remotoorigin=http://100.68.242.27:30000/george/itca_api_sap_wms.git(HTTP sin cifrar, red interna; confirmar que el repositorio sea privado). Etiquetav2.1.7.0= último estado antes de la limpieza de código. appsettings.jsonyappsettings.*.jsonestán en.gitignore(solo se versionaappsettings.example.json); las credenciales no están en el historial (verificado congit 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.
- SolicitudTransferencia:
PATCH /api/SolicitudTransferencia/{docEntry}yPOST /api/SolicitudTransferencia/{docEntry}/cerrar. - Picking diurno/nocturno: campo
Notificacion(early-return enPickingRepository.CreatetrasHelperProcesoPiciking.Set, solo paraProceso = "ULTIMA MILLA"; DESPACHO/PICKING generan NC sin depender de él) yPOST /api/Picking/HojaRuta/{docEntry}/Cerrar. ConnectionServiceLayer:PatchNoContentAsyncyPostActionAsync(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.PostReOpentrata el204sin cuerpo como éxito (antes fallaba al marcarExitosobrenully 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íneaBaseLine); 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 endocs/PICKING.md. - v2.1.5.0 — log del JSON enviado al Service Layer cuando SAP lo rechaza
(cualquier documento, no solo la NC):
ConnectionServiceLayerllama aErrorLogger(asignado enStartupaNet.Data/HelperData/Log/HelperLogServiceLayer.AddError) en los fallos dePostAsync,PatchAsyncSBAyPatchNoContentAsync. Guarda enITC_WMS_SAP.ITCA_LOG_INTEGRACION:ORIGEN = "ServiceLayer",PROCESO = "ServiceLayer Error",NRO_ORDEN= ruta del recurso (p. ej.CreditNotes),DOCENTRY=BaseEntryde 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 cubrePostActionAsync(cuerpo{}) niPostReOpen/PostClose. Las columnasPROCESO,NRO_ORDENyDOCENTRYsonVARCHAR(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 delcodigoSubAlmacendel 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 (elLoteProductodel 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íaFC10. Pendiente: validar con contabilidad la serie de boletas, y que Recibo no genera transferencias por almacén destino (nunca llenaU_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, elthrowinalcanzable dePatchAsyncSBA,HelperDB, 11 propiedades deRepositoryWrappersin uso, variablesTotalDetalle_Parcial/_Invoice/SerieOrigeny unifvacío enCreateHojaRuta) y se agregaron comentarios en Picking, Recibo,ConnectionServiceLayer,CreditNotesRepository,InvoiceRepositoryyRepositoryWrapper. Además se unificóLoginPost()enLogin()(eran idénticos; las 4 llamadas aLoginPostahora llaman aLogin) y se quitaron dos copias exactas sin llamadores:HelperHojaRuta.GetConsolidado(quedaHelperStock.GetConsolidado) yHRRepository.UpdateCreateCreditNotes(quedaCreditNotesRepository). Sigue pendiente: código comentado,PatchAsyncSBA, repositorios de compras sin uso (SetCreatePurchaseInvoicesduplicado enPurchaseOrdersRepository) y el resto de la redundancia (serieBC10/FC10y cabecera de la NC).PostAsync,PostReOpenyPostClosedeConnectionServiceLayercomparten ahora un núcleo privado (EnviarPostAsync: con/sin cuerpo, acepta o no el 204); se verificó con un servidor simulado que el resultado es idéntico al anterior (reintento por 401, 204 sin cuerpo, rechazo y log).PatchAsyncSBAsigue aparte: su manejo de errores es distinto y mantiene su bug del 204 (sin marcar éxito; el único llamador ignora el resultado). 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. - v2.1.9.0 — Transferencia desde ALM99 (importaciones): WMS recibe por partes; cada
entrada de mercadería (base: factura de reserva,
BaseType 18) va aALM99y, tras el costeo, WMS notifica una transferencia por entrada enviando enNumOrdenelDocNumde la factura de reserva y en el detalle los artículos/cantidades de esa entrada. Si el JSON no traeDocEntryEM,TransferenciaRepositorybusca por HANA (HelperInvoice.GetEntradasPorFactura:OPCH.isIns='Y'→PDN1→OPDN, sin anuladas; una entrada ya tiene transferencia si la línea tieneTargetType 67y suOWTRno está anulada), compara soloItemCodey cantidad (sumada por artículo) contra cada entrada y transfiere la más antigua que coincida y no esté transferida (EntradaImportacion.Elegir). Las líneas de la transferencia salen de la entrada (lotes reales, validando que cubran la cantidad) con base en ella. Errores claros: ninguna coincide / todas ya transferidas. Si la factura no tiene entradas se mantiene el comportamiento anterior (lotes del stock de HANA, sin amarre). ConDocEntryEMinformado se respeta (antes reventaba con referencia nula si la entrada o la línea no existían). Sin probar contra SAP: validar la consulta, queisIns='Y'sea factura de reserva y que SAP acepteBaseType "PurchaseDeliveryNotes"en la línea deStockTransfers. Detalle, errores y diagnóstico endocs/TRANSFERENCIA_IMPORTACION.md. Probado con datos reales (SQL Server) solo la consulta: entradas de 1 y 2 líneas, y una transferencia cancelada libera la entrada. - v2.1.10.0 — solo versión (sin cambios de comportamiento):
Version,AssemblyVersionyFileVersiondelcsprojquedan iguales (2.1.10.0). Swagger muestraAssemblyVersion(Startup.cs:OpenApiInfo.Version); si Swagger muestra otro número el servidor corre binarios viejos (pool sin reiniciar, carpeta equivocada o sitio desdebin\Debug). - v2.1.11.0 — tabla de log configurable y lotes de la NC de Recibo: (1) la tabla de log sale de
Hana:logTableenappsettings.json(LocalData.LogTable; por defectoITCA_LOG_INTEGRACIONpara QA/Desarrollo, producción usaITCA_LOG_INTEGRACION_PROD); el esquema sigue fijo enITC_WMS_SAP. Aplica aB_LogyHelperLogServiceLayer. (2) Recibo/Devolución: si el reparto de lotes (stock HANA o factura) no cubre la cantidad de la línea, el resto va a un lote nuevo por fecha/hora (antes SAP respondía "No es posible añadir una línea sin la selección completa de los números de serie/lote"); una línea sin equivalente en la factura ya no revienta con referencia nula. Sin probar contra SAP. - Sin probar contra SAP: confirmar con la factura 292410 que SAP devuelve
BaseType/BaseEntryen las líneas yBatchNumbersen las de la Entrega.
Cambios de configuración y correcciones hechas en esta carpeta
- Credenciales y esquema HANA en
appsettings.json, secciónHana(server,user,password,schemaopcional), leída porLocalData.ConfiguredesdeStartup. Antes estaban fijas en el código (LocalData.cs,Log/B_Log.cs). El esquema sale deHana:schemao, si no está, deSapServiceLayer:company; si falta la secciónHanao el esquema, la app no arranca (error claro). Ya no hayDB_NAMEfijo. - Precio promedio solo en entradas (
TipoMovimiento "01") enInventarioRepository.Create(los dos chequeos:SubAlmacenyAlmacen). Si el artículo no tiene stock, se conserva elPrecioPromediodel 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:PriceAfterVATlleva el precio del request. El chequeo de stock de la rama de salida dePickingRepository(~línea 363) no se tocó. - Lote de 100 líneas (
InventarioRepository.Create):var Inventario = entidadreutilizaba 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 leeentidad_inventario.Detalle. - SQL injection: parametrizadas las consultas de
HelperProcesoPiciking,HelperStock,HelperInventario,HelperInvoice,HelperCorrelativo,HelperHojaRutayHelperProcesoPermitido(?+HanaParameter). El esquema sigue interpolado (viene de configuración, no del request). ITCA_API_SAP_WMS.xmlahora se genera también en Release (sin eso Swagger revienta conFileNotFoundExceptionen unpublish -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 un204real devuelvenullsin marcar éxito.- El cliente HTTP
bypass-ssl-validationacepta cualquier certificado TLS hacia el Service Layer (se quitó el métodoValidarCertificado, que no se usaba). appsettings.json(fuera de git, en.gitignore) contiene credenciales reales en texto plano (SAP Service Layer, HANAB1ADMIN, semilla JWT). Rotar la contraseña deB1ADMIN(estuvo en el código fuente) y evaluar un usuario HANA de mínimos permisos.- Los logs (
B_LogyHelperLogServiceLayer) escriben en el esquema fijoITC_WMS_SAP(ITCA_LOG_INTEGRACION), no enLocalData.Schema; si la tabla está en otro esquema elINSERTfalla.B_Log.Addno tienetry/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 conFC10antes de la 2.1.7.0. - Recibo (Devolución) no genera transferencias por almacén destino: nunca llena
U_ITC_ALMDESen 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.