Documentar la transferencia desde ALM99 (docs/TRANSFERENCIA_IMPORTACION.md) y comentar el codigo
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d53d5d07c5
commit
3111bb3842
5 files changed
+117
-2
No files matched your search
@@ -0,0 +1,102 @@
|
||||
# Transferencia de stock desde ALM99 (importaciones) — v2.1.9.0
|
||||
|
||||
Documento de soporte. Código: `Net.Data/WMS/Transferencia/TransferenciaRepository.cs` (bloque `ALM99`),
|
||||
`Net.Data/WMS/Transferencia/EntradaImportacion.cs` (elección de la entrada) y
|
||||
`Net.Data/HelperData/Invoices/HelperInvoice.GetEntradasPorFactura` (consulta HANA).
|
||||
Endpoint: `POST /api/Transferencia`.
|
||||
|
||||
## Proceso de negocio
|
||||
|
||||
1. En SAP se crea una **Factura de Reserva de proveedores** y se envía al WMS para su recepción.
|
||||
2. El WMS recibe **por partes**: por cada recepción crea una **Entrada de Mercadería**
|
||||
(`PurchaseDeliveryNotes`) enlazada a la factura (`BaseType 18`, `BaseEntry`, `BaseLine`).
|
||||
Hay una o varias entradas por factura y todas ingresan al almacén **ALM99** (costeo).
|
||||
El WMS no guarda el `DocEntry` de las entradas, solo sabe qué artículos recibió en cada una.
|
||||
3. En SAP se hace el costeo (precio de entrega) de las entradas.
|
||||
4. Terminado el costeo, el WMS notifica **una transferencia por entrada** hacia el almacén final.
|
||||
|
||||
## JSON que envía el WMS
|
||||
|
||||
- `numorden` = **DocNum de la factura de reserva** (único).
|
||||
- `codigoSubAlmacenOrigen` = `ALM99`; `codigoSubAlmacenDestino` = almacén final (p. ej. `ALM21`).
|
||||
- `docEntry` = 0 (no hay solicitud de traslado); `docEntryEM` no se envía.
|
||||
- `detalle` = los artículos y cantidades **de una sola entrada**. Solo se usan `codigoarticulo`
|
||||
y `cantidadpedida`; `item` y `loteproducto` se ignoran en este caso.
|
||||
|
||||
## Qué hace la API (origen = ALM99 y sin `docEntryEM`)
|
||||
|
||||
1. Consulta HANA (`HelperInvoice.GetEntradasPorFactura`): factura `OPCH` con `DocNum = numorden`
|
||||
y `isIns = 'Y'` (= factura de reserva) → líneas `PDN1` con `BaseType 18` y `BaseEntry` = factura
|
||||
→ entrada `OPDN` no anulada (`CANCELED = 'N'`).
|
||||
2. Una entrada **ya tiene transferencia** si la línea tiene `TargetType = 67` y su `TrgetEntry`
|
||||
apunta a una transferencia `OWTR` con `CANCELED = 'N'`. Una transferencia anulada libera la entrada.
|
||||
3. `EntradaImportacion.Elegir` compara, por entrada, el conjunto `ItemCode` → cantidad (sumada por
|
||||
artículo) contra el detalle del JSON (también sumado). Debe coincidir **exacto** (mismos artículos,
|
||||
mismas cantidades, tolerancia 0.0001). Se toma la **entrada más antigua** (menor `DocEntry`) que
|
||||
coincida y no tenga transferencia.
|
||||
4. Se lee la entrada por Service Layer (`PurchaseDeliveryNotes(docEntry)`) y las líneas de la
|
||||
transferencia salen **de la entrada**: artículo, cantidad, lotes reales y base
|
||||
(`BaseType "PurchaseDeliveryNotes"`, `BaseEntry`, `BaseLine` = línea de la entrada). Si los lotes
|
||||
de una línea no suman su cantidad, responde error antes de enviar a SAP.
|
||||
5. Se envía `StockTransfers` con `U_SYP_MDMT = "21"`.
|
||||
|
||||
## Respuestas de error (400, mensaje en la respuesta y en `ITCA_LOG_INTEGRACION`)
|
||||
|
||||
| Mensaje | Causa |
|
||||
|---|---|
|
||||
| `SAP: Ninguna entrada de la factura de reserva X coincide con los articulos y cantidades enviados. Entradas pendientes de transferir (DocNum): ...` | El JSON no es igual a ninguna entrada (falta/sobra un artículo o cambia una cantidad). Lista las entradas aún sin transferir para comparar. |
|
||||
| `SAP: Todas las entradas de la factura de reserva X con esos articulos y cantidades ya estan transferidas: entrada N ya transferida en la transferencia M` | Reintento del mismo JSON o entrada ya transferida (evita duplicados). |
|
||||
| `SAP: Los lotes de la linea L (item) de la entrada N no cubren la cantidad Q` | La entrada tiene lotes que no suman la cantidad de la línea. |
|
||||
| `SAP: La entrada de mercaderia N no se puede leer` | Falló el GET al Service Layer. |
|
||||
| Error de SAP al crear `StockTransfers` | Ver la fila `PROCESO='ServiceLayer Error'` (JSON enviado + mensaje de SAP). |
|
||||
|
||||
## Otros casos del mismo endpoint (no cambiaron)
|
||||
|
||||
- **Transferencia simple** (origen distinto de ALM99, `docEntry = 0`): lotes por stock HANA (FEFO), sin base.
|
||||
- **Con solicitud de traslado** (`docEntry ≠ 0`): la solicitud es la base y se cierra al terminar.
|
||||
- **ALM99 con `docEntryEM` informado**: se respeta; lotes y base de esa entrada, amarrando
|
||||
`BaseLine` del JSON con `BaseLine` de la entrada. Si la entrada o la línea no existen responde error claro.
|
||||
- **ALM99 cuando la factura no tiene entradas** (o `numorden` no es una factura de reserva): se mantiene el
|
||||
comportamiento anterior (lotes del stock de HANA, sin amarre).
|
||||
|
||||
## Verificado y pendiente
|
||||
|
||||
- Verificado con datos reales (SQL Server): la consulta encuentra las entradas por `BaseType 18` y
|
||||
`isIns='Y'`; muestra el estado de transferencia por línea (entradas con 1 y con 2 líneas) y una
|
||||
transferencia **cancelada** vuelve a dejar la entrada libre (`TransferenciaDocEntry = 0`).
|
||||
- Verificado con simulación: la lógica de `Elegir` (coincidencia, entrada más antigua, ya transferida, no coincide).
|
||||
- **Pendiente de confirmar contra SAP/HANA reales**: que la consulta corra en HANA (la API usa HANA);
|
||||
que SAP acepte `BaseType "PurchaseDeliveryNotes"` en las líneas de `StockTransfers`; y el caso en que
|
||||
una entrada de varias líneas tenga transferida solo una línea (hoy cuenta como ya transferida).
|
||||
|
||||
## Cómo diagnosticar ("no se genera la transferencia")
|
||||
|
||||
1. Ver la fila en `"ITC_WMS_SAP"."ITCA_LOG_INTEGRACION"` con `PROCESO = 'Transferencia'` y
|
||||
`NRO_ORDEN = <numorden>`: trae el JSON del WMS y la respuesta (el mensaje de la tabla de arriba).
|
||||
2. Ejecutar la consulta de `HelperInvoice.GetEntradasPorFactura` (versión SQL Server/HANA al final) con el
|
||||
`DocNum`: si no devuelve filas, la factura no existe, no es de reserva (`isIns`) o sus entradas no tienen
|
||||
`BaseType 18`; si `TransferenciaDocEntry ≠ 0`, esa entrada ya fue transferida.
|
||||
3. Comparar artículos y cantidades del JSON contra las filas de esa entrada.
|
||||
|
||||
```sql
|
||||
-- HANA (reemplazar <ESQUEMA> y el DocNum de la factura de reserva)
|
||||
SELECT E."DocEntry", E."DocNum", L."LineNum", L."ItemCode", L."Quantity",
|
||||
CASE WHEN L."TargetType" = 67 AND W."DocEntry" IS NOT NULL AND W."CANCELED" = 'N'
|
||||
THEN W."DocEntry" ELSE 0 END AS "TransferenciaDocEntry"
|
||||
FROM "<ESQUEMA>"."OPCH" F
|
||||
INNER JOIN "<ESQUEMA>"."PDN1" L ON L."BaseType" = 18 AND L."BaseEntry" = F."DocEntry"
|
||||
INNER JOIN "<ESQUEMA>"."OPDN" E ON E."DocEntry" = L."DocEntry"
|
||||
LEFT JOIN "<ESQUEMA>"."OWTR" W ON L."TargetType" = 67 AND W."DocEntry" = L."TrgetEntry"
|
||||
WHERE F."DocNum" = 262000082 AND F."isIns" = 'Y' AND E."CANCELED" = 'N'
|
||||
ORDER BY E."DocEntry", L."LineNum";
|
||||
```
|
||||
|
||||
En SQL Server es la misma consulta sin comillas dobles y con `[<BASE>].dbo.OPCH`, etc.
|
||||
|
||||
## Historia
|
||||
|
||||
Antes (también en el código del desarrollador anterior y en el commit inicial) el bloque dependía de
|
||||
`DocEntryEM`, que el WMS no envía: nunca se amarraba a la entrada y los lotes salían solo del stock de HANA
|
||||
(sin validar que cubrieran la cantidad). La versión original buscaba la entrada por `NumOrden` con
|
||||
`HelperInvoice.Get` (procedimiento `ITCA_WMS_SAP_GetEntradaPorImportacion`, un solo `DocEntry`), que quedó
|
||||
comentado; no servía para varias entradas por factura. Esa función sigue en el código sin llamadores.
|
||||
Reference in new issue
Block a user