Commit inicial: ITCA_API_SAP_WMS (.NET Core 3.1)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
2b82744eb8
168 files changed
+11066
No files matched your search
@@ -0,0 +1,149 @@
|
||||
# ITCA_API_SAP_WMS (.NET) — build, publish y despliegue en IIS
|
||||
|
||||
API de integración WMS ↔ SAP Business One (Service Layer + HANA directo),
|
||||
**ASP.NET Core 3.1**. Para contexto de por qué este proyecto sigue activo
|
||||
(hay una reescritura en Python en paralelo) ver [`CLAUDE.md`](./CLAUDE.md).
|
||||
|
||||
## Requisitos para compilar
|
||||
|
||||
- .NET Core 3.1 SDK.
|
||||
- Cliente HANA .NET instalado en
|
||||
`C:\Program Files\sap\hdbclient\dotnetcore\v2.1\Sap.Data.Hana.Core.v2.1.dll`
|
||||
(ruta hardcodeada vía `HintPath` en los `.csproj` de `Net.Data` y
|
||||
`Net.Business.Services` — sin esto no compila ningún proyecto que dependa
|
||||
de HANA).
|
||||
- **Compilar desde macOS/Linux**: el `HintPath` es relativo (6 niveles hacia
|
||||
arriba + `Program Files\sap\...`). Se puede compilar copiando el repo a
|
||||
`<raiz>/a/b/c/d/repo/` y poniendo la DLL en
|
||||
`<raiz>/Program Files/sap/hdbclient/dotnetcore/v2.1/` — así el `HintPath`
|
||||
resuelve sin tocar los `.csproj`. (Pasar `AssemblySearchPaths` por línea
|
||||
de comandos NO sirve: rompe la resolución del framework.)
|
||||
|
||||
## Configuración de HANA (`appsettings.json`, sección `Hana`)
|
||||
|
||||
Las credenciales y el esquema de HANA ya **no** están fijos en el código; hay
|
||||
un único lugar, `LocalData.Configure(...)` (`Net.Data/LocalData.cs`), que se
|
||||
llama desde `Startup`:
|
||||
|
||||
```json
|
||||
"Hana": {
|
||||
"server": "192.168.0.13:30015",
|
||||
"user": "<usuario>",
|
||||
"password": "<password>",
|
||||
"schema": "<opcional>"
|
||||
}
|
||||
```
|
||||
|
||||
- `schema` es opcional: si no está, se usa `SapServiceLayer:company` (si no hay ninguno de los dos la app no arranca, no hay valor por defecto), de modo
|
||||
que lecturas por HANA (`CALL "<esquema>"."ITCA_..."`) y escrituras por
|
||||
Service Layer apunten siempre a la misma compañía.
|
||||
- **Si falta la sección `Hana` la app no arranca** (`InvalidOperationException`
|
||||
clara en `LocalData.Configure`). Al desplegar sobre un sitio existente hay
|
||||
que agregarla a su `appsettings.json` **antes** de iniciar el pool.
|
||||
|
||||
## Correr localmente
|
||||
|
||||
```
|
||||
dotnet run --project Net.Business.Services
|
||||
```
|
||||
|
||||
Swagger queda en la raíz (`RoutePrefix = ""` en `Startup.cs`): `http://localhost:<puerto>/`.
|
||||
|
||||
## Generar el publish para IIS
|
||||
|
||||
```
|
||||
dotnet publish Net.Business.Services/Net.Business.Services.csproj -c Release -r win-x64 --self-contained false -o <carpeta-salida>
|
||||
```
|
||||
|
||||
- `-r win-x64 --self-contained false`: genera un `.exe` nativo (apphost) de
|
||||
64 bits que no incluye el runtime — depende de que el servidor ya tenga el
|
||||
**ASP.NET Core 3.1 Hosting Bundle** instalado (confirmarlo con
|
||||
`dotnet --list-runtimes` en el servidor: debe listar
|
||||
`Microsoft.AspNetCore.App 3.1.x` y `Microsoft.NETCore.App 3.1.x`).
|
||||
- El `.xml` de comentarios (`ITCA_API_SAP_WMS.xml`, que Swagger necesita vía
|
||||
`IncludeXmlComments` en `Startup.cs`) ya se genera solo en Release desde
|
||||
que se sacó la condición `Debug|AnyCPU` del `.csproj` — si en algún
|
||||
momento vuelve a faltar en el output del publish, revisar que esa
|
||||
propiedad (`DocumentationFile`) siga sin estar condicionada a Debug.
|
||||
- `dotnet publish` transforma automáticamente el `processPath` del
|
||||
`web.config` para que apunte al `.exe` publicado — **no** copiar el
|
||||
`web.config` del código fuente (ese apunta a `bin\Debug\...`, es el de
|
||||
desarrollo) a una carpeta de publish.
|
||||
|
||||
## Desplegar/actualizar un sitio en IIS
|
||||
|
||||
### Si el sitio YA corre desde una carpeta de publish (actualización de versión)
|
||||
|
||||
1. Detener el Application Pool del sitio (libera los locks de los `.dll`/`.exe`).
|
||||
2. Copiar el contenido del nuevo publish **sin tocar** `appsettings.json` ni
|
||||
`web.config` existentes — esos quedan tal cual están configurados en ese
|
||||
servidor/ambiente (pueden tener valores distintos a los del repo, ej.
|
||||
`SapServiceLayer:company` apuntando a una base SAP distinta de QA/prod).
|
||||
3. Iniciar el Application Pool.
|
||||
|
||||
### Si el sitio corre directo desde el código fuente (`bin\Debug\...`)
|
||||
|
||||
Así corre al menos un ambiente real (`CLONE-SRV-WEB`, ruta física
|
||||
`...\BackEnd\Desarrollo\BackEnd\Net.Business.Services`, `web.config` con
|
||||
`processPath="bin\Debug\netcoreapp3.1\ITCA_API_SAP_WMS.exe"`) — ahí **no**
|
||||
se usa `dotnet publish`, se compila in situ:
|
||||
|
||||
1. Detener el Application Pool primero (si no, falla la compilación por
|
||||
archivos en uso).
|
||||
2. Copiar los `.cs`/`.csproj` que cambiaron a las mismas rutas relativas
|
||||
dentro de la solución en el servidor (no hace falta tocar ningún
|
||||
`.csproj` para agregar archivos nuevos — son proyectos SDK-style con
|
||||
glob automático de `**/*.cs`).
|
||||
3. Compilar la solución ahí (Visual Studio → Build Solution en Debug, o
|
||||
`dotnet build` desde la carpeta de la solución).
|
||||
4. Iniciar el Application Pool.
|
||||
|
||||
### Checklist de configuración del Application Pool (IIS Manager, una sola vez por pool nuevo)
|
||||
|
||||
- **.NET CLR Version**: Sin código administrado (No Managed Code).
|
||||
- **Configuración avanzada → Habilitar aplicaciones de 32 bits**: **False**
|
||||
(el `.exe`/DLLs son de 64 bits — con esto en True da
|
||||
`500.32 Failed to load .NET Core host`, bitness mismatch).
|
||||
- **Configuración avanzada → Cargar perfil de usuario (Load User Profile)**:
|
||||
**True** — sin esto, arranque falla con `ErrorCode '0x8007023e'`
|
||||
(excepción no manejada al iniciar el proceso in-process).
|
||||
- **Permisos de carpeta**: `IIS AppPool\<NombreDelPool>` con **Lectura y
|
||||
ejecución** sobre toda la carpeta del sitio, y **Modificar** sobre la
|
||||
subcarpeta `logs\` (para que `stdoutLogEnabled` pueda escribir si hace
|
||||
falta diagnosticar).
|
||||
|
||||
### Diagnóstico de errores de arranque
|
||||
|
||||
1. Visor de eventos de Windows → Registros de Windows → Aplicación → buscar
|
||||
el evento de `IIS AspNetCoreModule V2` más reciente — casi siempre trae
|
||||
el error real.
|
||||
2. Si no alcanza, poner `stdoutLogEnabled="true"` en el `web.config` de esa
|
||||
carpeta y revisar `.\logs\stdout_*.log` después de reciclar el pool.
|
||||
|
||||
### Editar `appsettings.json` de un sitio ya desplegado
|
||||
|
||||
No hace falta detener el Application Pool para editarlo (no queda
|
||||
bloqueado como los binarios) — pero conviene **reciclar el pool** después
|
||||
de guardar, para garantizar que el valor nuevo se relea (el host usa
|
||||
`Host.CreateDefaultBuilder`, que ya trae `reloadOnChange: true` para
|
||||
`appsettings.json`, pero no vale la pena depender de eso para un cambio
|
||||
puntual).
|
||||
|
||||
El nombre de la base SAP (`CompanyDB`) se configura en
|
||||
`SapServiceLayer:company` dentro de `appsettings.json` — lo lee
|
||||
`ConnectionServiceLayer.cs` (`_company = configuration["SapServiceLayer:company"]`)
|
||||
para armar el body del `Login` contra el Service Layer.
|
||||
|
||||
## Riesgos de seguridad heredados (documentados, no corregidos sin coordinar antes)
|
||||
|
||||
- `appsettings.json` tiene credenciales reales en texto plano (SAP Service
|
||||
Layer, **HANA `B1ADMIN`**, semilla JWT) — no hay `git` en esta carpeta; si alguna vez se versiona o se sube
|
||||
a un remoto compartido, hay que decidir qué hacer con ese archivo primero.
|
||||
- `B1ADMIN` es un usuario administrador de SAP B1; la API solo necesita
|
||||
ejecutar los `ITCA_*` y leer algunas tablas. Conviene un usuario HANA de
|
||||
permisos mínimos y rotar la contraseña (estuvo en texto plano en el código
|
||||
y en el historial git del repo antiguo archivado).
|
||||
- `ValidarCertificado` en `ConnectionServiceLayer.cs` acepta cualquier
|
||||
certificado TLS (`return true;` siempre) — bypass de validación de
|
||||
certificado hacia el Service Layer, igual criterio que
|
||||
`SERVICE_LAYER_VERIFY_SSL=false` en la reescritura Python.
|
||||
Reference in new issue
Block a user