Picking: Notificacion=cierre solo se exige con Proceso ULTIMA MILLA. Versión 2.1.2.0

DESPACHO y PICKING vuelven a generar nota de crédito sin depender de
Notificacion. Documentada la regla Proceso + Notificacion.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
GeorgeandClaude Sonnet 5.5 committed 2026-10-14 08:47:44 -05:00
1 parent e31524ab6b
commit e475b7f48c
4 files changed
+51 -21

No files matched your search

+10 -1
View File
@@ -16,11 +16,20 @@ Detalle técnico en `docs/PORTE_FUNCIONALIDAD_NUEVA.md`,
1. **SolicitudTransferencia**: `PATCH /api/SolicitudTransferencia/{docEntry}` y 1. **SolicitudTransferencia**: `PATCH /api/SolicitudTransferencia/{docEntry}` y
`POST /api/SolicitudTransferencia/{docEntry}/cerrar`. `POST /api/SolicitudTransferencia/{docEntry}/cerrar`.
2. **Picking diurno/nocturno**: campo `Notificacion` (early-return en 2. **Picking diurno/nocturno**: campo `Notificacion` (early-return en
`PickingRepository.Create` tras `HelperProcesoPiciking.Set`) y `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`. `POST /api/Picking/HojaRuta/{docEntry}/Cerrar`.
3. **`ConnectionServiceLayer`**: `PatchNoContentAsync` y `PostActionAsync` 3. **`ConnectionServiceLayer`**: `PatchNoContentAsync` y `PostActionAsync`
(métodos nuevos; los existentes no se tocaron). (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`.
## Cambios de configuración y correcciones hechas en esta carpeta ## Cambios de configuración y correcciones hechas en esta carpeta
- **Credenciales y esquema HANA en `appsettings.json`**, sección `Hana` - **Credenciales y esquema HANA en `appsettings.json`**, sección `Hana`
@@ -3,9 +3,9 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>netcoreapp3.1</TargetFramework>
<AssemblyName>ITCA_API_SAP_WMS</AssemblyName> <AssemblyName>ITCA_API_SAP_WMS</AssemblyName>
<Version>2.1.1</Version> <Version>2.1.2</Version>
<AssemblyVersion>2.1.1.0</AssemblyVersion> <AssemblyVersion>2.1.2.0</AssemblyVersion>
<FileVersion>2.1.1.0</FileVersion> <FileVersion>2.1.2.0</FileVersion>
<UserSecretsId>24763424-3300-4c85-87e3-503f8fdebd14</UserSecretsId> <UserSecretsId>24763424-3300-4c85-87e3-503f8fdebd14</UserSecretsId>
<!-- Antes solo estaba condicionado a Debug|AnyCPU - un "dotnet publish -c Release" <!-- Antes solo estaba condicionado a Debug|AnyCPU - un "dotnet publish -c Release"
(lo normal para IIS) se quedaba sin este archivo, y Startup.cs revienta con (lo normal para IIS) se quedaba sin este archivo, y Startup.cs revienta con
+4 -3
View File
@@ -120,11 +120,12 @@ namespace Net.Data.WMS.Picking
//=== REALIZA PROCESO COMPLETO DE ACTUALIZACION //=== REALIZA PROCESO COMPLETO DE ACTUALIZACION
HelperProcesoPiciking.Set(entidad.Proceso, entidad.IdEstadoCubico, entidad.DocEntry, entidad.CodMotivo, Proceso.Code); HelperProcesoPiciking.Set(entidad.Proceso, entidad.IdEstadoCubico, entidad.DocEntry, entidad.CodMotivo, Proceso.Code);
// === NUEVO (Picking diurno/nocturno): "notificacion" distinta de "cierre" // === Solo para el proceso "ULTIMA MILLA": "notificacion" distinta de "cierre"
// (o ausente) es la notificacion preliminar en tiempo real - solo actualiza // (o ausente) es la notificacion preliminar en tiempo real - solo actualiza
// estado en HANA (ya hecho arriba), NUNCA debe crear documentos en SAP. // estado en HANA (ya hecho arriba), NUNCA debe crear documentos en SAP.
// Default seguro: cualquier valor que no sea "cierre" exacto cae aca. // DESPACHO, PICKING y demas procesos no dependen de este campo.
if (!string.Equals(entidad.Notificacion, "cierre", StringComparison.OrdinalIgnoreCase)) if (string.Equals(entidad.Proceso, "ULTIMA MILLA", StringComparison.OrdinalIgnoreCase)
&& !string.Equals(entidad.Notificacion, "cierre", StringComparison.OrdinalIgnoreCase))
{ {
return resultadoTransaccion.GetInformacionResultado(entidad.DocEntry, entidad.NumOrden, "Estado actualizado correctamente", entidad); return resultadoTransaccion.GetInformacionResultado(entidad.DocEntry, entidad.NumOrden, "Estado actualizado correctamente", entidad);
} }
+34 -14
View File
@@ -22,11 +22,27 @@ recorre esas mismas facturas con un `FOR` de su lado llamando otra vez al
mismo endpoint pero en modo **cierre** (ahí sí se crean los documentos SAP), mismo endpoint pero en modo **cierre** (ahí sí se crean los documentos SAP),
y al final cierra la hoja de ruta completa **una sola vez**. y al final cierra la hoja de ruta completa **una sola vez**.
## Regla Proceso + Notificacion (versión 2.1.2.0)
`Notificacion` **solo se valida cuando `Proceso = "ULTIMA MILLA"`**. En los
demás procesos el campo se ignora.
| `Proceso` | `Notificacion` | Resultado |
|---|---|---|
| `ULTIMA MILLA` | `"cierre"` | Lógica completa: crea documentos en SAP (solicitud de devolución, estado 23). |
| `ULTIMA MILLA` | ausente u otro valor | Solo actualiza estado en HANA; **no** crea nada en SAP. |
| `DESPACHO` | cualquiera / ausente | Lógica completa siempre: NC y transferencias automáticas (estados 5 y 6). |
| `PICKING` | cualquiera / ausente | Lógica completa siempre: NC y transferencias automáticas (estado 13). |
Historial: en 2.1.1.0 el filtro se aplicaba a todos los procesos, por lo que
DESPACHO y PICKING no generaban la NC si no llegaba `"cierre"`. Corregido en
2.1.2.0.
## Resumen del contrato ## Resumen del contrato
| Método | Ruta | Cambia hoy | Qué hace | | Método | Ruta | Cambia hoy | Qué hace |
|---|---|---|---| |---|---|---|---|
| `POST` | `/api/picking` | **Sí** — agrega campo `Notificacion` | `"cierre"` → lógica actual completa (crea documento SAP); cualquier otro valor/ausente → solo actualiza estado en HANA, nunca toca SAP. | | `POST` | `/api/picking` | **Sí** — agrega campo `Notificacion` | **Solo con `Proceso = "ULTIMA MILLA"`**: `"cierre"` → lógica completa (crea documento SAP); cualquier otro valor/ausente → solo actualiza estado en HANA, nunca toca SAP. Con `DESPACHO`, `PICKING` y demás procesos el campo se ignora y la lógica corre siempre (NC y transferencias). |
| `POST` | `/api/picking/ruta` | No | Sin cambios — `CreateHojaRuta` ya existe y sigue igual. | | `POST` | `/api/picking/ruta` | No | Sin cambios — `CreateHojaRuta` ya existe y sigue igual. |
| `POST` | `/api/picking/hojaruta/{docEntry}/cerrar` | **Nuevo** | Cierra el UDO `ARD_PHR` completo en SAP. Sin body. | | `POST` | `/api/picking/hojaruta/{docEntry}/cerrar` | **Nuevo** | Cierra el UDO `ARD_PHR` completo en SAP. Sin body. |
@@ -36,7 +52,7 @@ y al final cierra la hoja de ruta completa **una sola vez**.
**Archivo**: `Net.Business.Entities/WMS/Picking/BE_PickingRequest.cs` — agregar: **Archivo**: `Net.Business.Entities/WMS/Picking/BE_PickingRequest.cs` — agregar:
```csharp ```csharp
public string Notificacion { get; set; } // "preliminar" | "cierre"; cualquier otro valor o ausente = "preliminar" public string Notificacion { get; set; } // solo se evalua con Proceso "ULTIMA MILLA": "cierre" | otro/ausente = preliminar
``` ```
**Archivo**: `Net.Business.DTO/WMS/Picking/Dto_PickingRequest.cs` — agregar la **Archivo**: `Net.Business.DTO/WMS/Picking/Dto_PickingRequest.cs` — agregar la
@@ -73,8 +89,10 @@ alcanza con un `if` adentro del mismo método).
HelperProcesoPiciking.Set(entidad.Proceso, entidad.IdEstadoCubico, entidad.DocEntry, entidad.CodMotivo, Proceso.Code); HelperProcesoPiciking.Set(entidad.Proceso, entidad.IdEstadoCubico, entidad.DocEntry, entidad.CodMotivo, Proceso.Code);
// <-- linea 96 actual, sin tocar // <-- linea 96 actual, sin tocar
// === NUEVO: notificacion preliminar (diurna) - nunca toca SAP // === Solo ULTIMA MILLA: notificacion preliminar (diurna) - nunca toca SAP.
if (!string.Equals(entidad.Notificacion, "cierre", StringComparison.OrdinalIgnoreCase)) // DESPACHO / PICKING no dependen de Notificacion.
if (string.Equals(entidad.Proceso, "ULTIMA MILLA", StringComparison.OrdinalIgnoreCase)
&& !string.Equals(entidad.Notificacion, "cierre", StringComparison.OrdinalIgnoreCase))
{ {
return resultadoTransaccion.GetInformacionResultado(entidad.DocEntry, entidad.NumOrden, "Estado actualizado correctamente", entidad); return resultadoTransaccion.GetInformacionResultado(entidad.DocEntry, entidad.NumOrden, "Estado actualizado correctamente", entidad);
} }
@@ -85,8 +103,10 @@ if (!string.Equals(entidad.Notificacion, "cierre", StringComparison.OrdinalIgnor
``` ```
Es decir: **todo lo que hoy hace `Create()` (líneas 45-341 completas)** sigue Es decir: **todo lo que hoy hace `Create()` (líneas 45-341 completas)** sigue
siendo exactamente la lógica de `notificacion == "cierre"` — no se toca nada siendo exactamente la lógica de cierre — no se toca nada de ahí. Solo se
de ahí. Solo se agrega el `if` de corte después de la línea 96. agrega el `if` de corte después de la línea 96, y **únicamente para
`ULTIMA MILLA`**. Para `DESPACHO` y `PICKING` la NC se genera sin importar
`Notificacion`.
> **Nota de contrato**: `detalle` ya es obligatorio hoy en este endpoint (la > **Nota de contrato**: `detalle` ya es obligatorio hoy en este endpoint (la
> validación de arriba lo necesita para desambiguar `Existe > 1`), así que no > validación de arriba lo necesita para desambiguar `Existe > 1`), así que no
@@ -96,15 +116,15 @@ de ahí. Solo se agrega el `if` de corte después de la línea 96.
### Bodies de ejemplo ### Bodies de ejemplo
**Notificación preliminar** (reparto en curso — `Notificacion` ausente o **Notificación preliminar** (solo `ULTIMA MILLA`, reparto en curso —
distinto de `"cierre"`): `Notificacion` ausente o distinto de `"cierre"`):
```json ```json
{ {
"numOrden": "OT-2026-001", "numOrden": "OT-2026-001",
"docEntry": 500, "docEntry": 500,
"proceso": "DESPACHO", "proceso": "ULTIMA MILLA",
"codMotivo": "M01", "codMotivo": "M01",
"idEstadoCubico": 6, "idEstadoCubico": 23,
"codigoAlmacen": "ALM01", "codigoAlmacen": "ALM01",
"detalle": [ "detalle": [
{ "item": 0, "codigoArticulo": "ART-001", "cantidadPedida": 3, "estado": "C" } { "item": 0, "codigoArticulo": "ART-001", "cantidadPedida": 3, "estado": "C" }
@@ -112,15 +132,15 @@ distinto de `"cierre"`):
} }
``` ```
**Cierre** (mismo shape, agrega `notificacion: "cierre"` — crea el documento **Cierre** (`ULTIMA MILLA`, mismo shape, agrega `notificacion: "cierre"` —
SAP real, misma respuesta que hoy): crea el documento SAP real, misma respuesta que hoy):
```json ```json
{ {
"numOrden": "OT-2026-001", "numOrden": "OT-2026-001",
"docEntry": 500, "docEntry": 500,
"proceso": "DESPACHO", "proceso": "ULTIMA MILLA",
"codMotivo": "M01", "codMotivo": "M01",
"idEstadoCubico": 6, "idEstadoCubico": 23,
"codigoAlmacen": "ALM01", "codigoAlmacen": "ALM01",
"notificacion": "cierre", "notificacion": "cierre",
"detalle": [ "detalle": [