Unificar la transferencia automatica de la NC en TransferenciaAutomaticaNC.Crear

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>
This commit is contained in:
GeorgeandClaude Sonnet 5.5 committed 2026-10-14 19:52:53 -05:00
1 parent 3bce3ed117
commit 3ea0aca535
4 files changed
+126 -299

No files matched your search

+5 -5
View File
@@ -98,8 +98,9 @@ transferencias siempre, sin depender de `Notificacion`. Detalle y tabla en
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 las transferencias automáticas
(3 copias en Picking/Recibo) y de los métodos POST/PATCH del cliente.
(`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.
@@ -164,9 +165,8 @@ Picking, columna `HORA` en `B_Log`. Lo que **no** se trajo: `Chatbots` y
`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.
- En Picking y Recibo, si la transferencia automática de stock falla, el `if`
de error está vacío: el fallo se ignora (la NC ya está creada) y no se informa
al consumidor.
- 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
@@ -0,0 +1,114 @@
using Microsoft.Extensions.Configuration;
using Net.Business.Entities.ServicesLayer.CreditNotes;
using Net.Business.Entities.ServicesLayer.StockTransfer;
using Net.Data.ServicesLayer.CreditNotes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
namespace Net.Data.ServicesLayer.StockTransfer
{
// Transferencias de stock automaticas de una nota de credito (Picking DESPACHO/PICKING y Recibo Devolucion).
// Antes este bloque estaba copiado 3 veces.
public static class TransferenciaAutomaticaNC
{
// Por cada almacen de origen (WarehouseCode) y almacen destino (U_ITC_ALMDES) distintos de las lineas de la NC
// crea una transferencia de stock en SAP, con las cantidades y lotes de esas lineas y la NC como referencia.
// Luego agrega a la NC una referencia por cada transferencia creada.
// OJO: si SAP rechaza una transferencia se ignora (la NC ya esta creada) y no se informa al consumidor.
public static void Crear(BE_CreditNotesNotes creditNotesNotes, int docEntryNC, IHttpClientFactory clientFactory, IConfiguration configuration, CreditNotesRepository creditNotesRepository)
{
List<string> ListaUnicaAlmacen = creditNotesNotes.DocumentLines.Select(x => x.WarehouseCode).Distinct().ToList();
List<int> ListDocEntry = new List<int>();
ListaUnicaAlmacen.ForEach(Almacen =>
{
List<string> ListaUnicaAlmDestino = creditNotesNotes.DocumentLines.Where(Linea => Linea.WarehouseCode == Almacen).ToList().Select(x => x.U_ITC_ALMDES).Distinct().ToList().Where(x => !string.IsNullOrEmpty(x)).ToList();
ListaUnicaAlmDestino.ForEach(Destino =>
{
if (Almacen != Destino)
{
BE_StockTransferAutomatico Transfer = new BE_StockTransferAutomatico();
Transfer.FromWarehouse = Almacen;
Transfer.ToWarehouse = Destino;
Transfer.DocDate = creditNotesNotes.DocDate;
Transfer.TaxDate = creditNotesNotes.DocDate;
Transfer.U_SYP_MDTS = "TSI";
Transfer.U_SYP_MDMT = "24";
Transfer.DueDate = creditNotesNotes.DocDueDate;
Transfer.PriceList = -2;
var ListaDetalle_PorAlmacen = creditNotesNotes.DocumentLines.Where(x => x.WarehouseCode == Almacen && x.U_ITC_ALMDES == Destino).ToList();
var ListaUnicaArticulo = ListaDetalle_PorAlmacen.Select(x => x.ItemCode).Distinct().ToList();
Transfer.StockTransferLines = new List<BE_StockTransferLine>();
//=== AGREGA DOCUMENTO REFERENCIA
Transfer.DocumentReferences = new List<BE_StockTransferDocumentReferences>
{
new BE_StockTransferDocumentReferences()
{
RefDocEntr = docEntryNC,
RefObjType = "rot_SalesCreditNote",
IssueDate = DateTime.Now,
Remark = "Nota de Credito",
}
};
ListaUnicaArticulo.ForEach(x =>
{
var ListLote = new List<BE_StockTransferLineBatchNumber>();
// Lotes de todas las lineas del articulo (si el mismo lote esta en varias lineas se suma)
ListaDetalle_PorAlmacen.Where(t => t.ItemCode == x).SelectMany(t => t.BatchNumbers).GroupBy(r => r.BatchNumber).ToList().ForEach(g =>
{
ListLote.Add(new BE_StockTransferLineBatchNumber()
{
BatchNumber = g.Key,
Quantity = g.Sum(r => r.Quantity)
});
});
Transfer.StockTransferLines.Add(new BE_StockTransferLine()
{
ItemCode = x,
ItemDescription = ListaDetalle_PorAlmacen.Where(t => t.ItemCode == x).FirstOrDefault().ItemDescription,
Quantity = Convert.ToDouble(ListaDetalle_PorAlmacen.Where(t => t.ItemCode == x).Sum(t => t.Quantity)),
WarehouseCode = Destino,
FromWarehouseCode = Almacen,
BatchNumbers = ListLote
});
});
//=== CREA INSTANCIA PARA CONECTAR A SAP
StockTransferRepository stockTransferRepository = new StockTransferRepository(clientFactory, configuration);
var ResultTransfer = stockTransferRepository.StockTransfer(Transfer).Result;
if (ResultTransfer.StatusCode != -1)
{
ListDocEntry.Add((int)ResultTransfer.Data.DocEntry);
}
}
});
});
// Referencia las transferencias creadas en la NC
if (ListDocEntry.Count > 0)
{
var listaReferencia = new List<BE_CreditNotesDocumentReferences>();
ListDocEntry.ForEach(x =>
{
listaReferencia.Add(new BE_CreditNotesDocumentReferences()
{
RefDocEntr = x,
IssueDate = DateTime.Now,
RefObjType = "rot_InventoryTransfer",
Remark = "Transferencias Automatica"
});
});
var credit = new
{
DocumentReferences = listaReferencia
};
var Actualizacion = creditNotesRepository.UpdateCreateCreditNotes(credit, docEntryNC).Result;
}
}
}
}
+4 -198
View File
@@ -299,108 +299,8 @@ namespace Net.Data.WMS.Picking
}
else
{
// Por cada almacen de origen y almacen destino (U_ITC_ALMDES) distintos se crea una transferencia de stock automatica
List<string> ListaUnicaAlmacen = creditNotesNotes.DocumentLines.Select(x => x.WarehouseCode).Distinct().ToList();
List<int> ListDocEntry = new List<int>();
ListaUnicaAlmacen.ForEach(Almacen =>
{
List<string> ListaUnicaAlmDestino = creditNotesNotes.DocumentLines.Where(Linea => Linea.WarehouseCode == Almacen).ToList().Select(x => x.U_ITC_ALMDES).Distinct().ToList().Where(x => !string.IsNullOrEmpty(x)).ToList();
ListaUnicaAlmDestino.ForEach(Destino =>
{
if (Almacen != Destino)
{
BE_StockTransferAutomatico Transfer = new BE_StockTransferAutomatico();
Transfer.FromWarehouse = Almacen;
Transfer.ToWarehouse = Destino;
Transfer.DocDate = creditNotesNotes.DocDate;
Transfer.TaxDate = creditNotesNotes.DocDate;
Transfer.U_SYP_MDTS = "TSI";
Transfer.U_SYP_MDMT = "24";
Transfer.DueDate = creditNotesNotes.DocDueDate;
Transfer.PriceList = -2;
var ListaDetalle_PorAlmacen = creditNotesNotes.DocumentLines.Where(x => x.WarehouseCode == Almacen && x.U_ITC_ALMDES == Destino).ToList();
var ListaUnicaArticulo = ListaDetalle_PorAlmacen.Select(x => x.ItemCode).Distinct().ToList();
Transfer.StockTransferLines = new List<BE_StockTransferLine>();
Transfer.DocumentReferences = new List<BE_StockTransferDocumentReferences>();
ListaUnicaArticulo.ForEach(x =>
{
var ListLote = new List<BE_StockTransferLineBatchNumber>();
// Lotes de todas las lineas del articulo (si el mismo lote esta en varias lineas se suma)
ListaDetalle_PorAlmacen.Where(t => t.ItemCode == x).SelectMany(t => t.BatchNumbers).GroupBy(r => r.BatchNumber).ToList().ForEach(g =>
{
ListLote.Add(new BE_StockTransferLineBatchNumber()
{
BatchNumber = g.Key,
Quantity = g.Sum(r => r.Quantity)
});
});
Transfer.StockTransferLines.Add(new BE_StockTransferLine()
{
ItemCode = x,
ItemDescription = ListaDetalle_PorAlmacen.Where(t => t.ItemCode == x).FirstOrDefault().ItemDescription,
Quantity = Convert.ToDouble(ListaDetalle_PorAlmacen.Where(t => t.ItemCode == x).Sum(t => t.Quantity)),
WarehouseCode = Destino,
FromWarehouseCode = Almacen,
BatchNumbers = ListLote
});
//=== AGREGA DOCUMENTO REFERENCIA
Transfer.DocumentReferences = new List<BE_StockTransferDocumentReferences>
{
new BE_StockTransferDocumentReferences()
{
RefDocEntr = (int)result_creditNotesRepository.Data.DocEntry,
RefObjType = "rot_SalesCreditNote",
IssueDate = DateTime.Now,
Remark = "Nota de Credito",
}
};
});
//=== CREA INSTANCIA PARA CONECTAR A SAP
StockTransferRepository stockTransferRepository = new StockTransferRepository(_clientFactory, _configuration);
var ResultTransfer = stockTransferRepository.StockTransfer(Transfer).Result;
// OJO: si la transferencia falla se ignora (la NC ya esta creada) y no se informa al consumidor
if (ResultTransfer.StatusCode == -1)
{
}
else
{
ListDocEntry.Add((int)ResultTransfer.Data.DocEntry);
}
}
});
});
// Referencia las transferencias creadas en la NC
if (ListDocEntry.Count > 0)
{
var listaReferencia = new List<BE_CreditNotesDocumentReferences>();
ListDocEntry.ForEach(x =>
{
listaReferencia.Add(new BE_CreditNotesDocumentReferences()
{
RefDocEntr = x,
IssueDate = DateTime.Now,
RefObjType = "rot_InventoryTransfer",
Remark = "Transferencias Automatica"
});
});
var credit = new
{
DocumentReferences = listaReferencia
};
var Actualizacion = _creditNotesRepository.UpdateCreateCreditNotes(credit, (int)result_creditNotesRepository.Data.DocEntry).Result;
}
// Transferencias de stock automaticas por almacen destino (U_ITC_ALMDES) y su referencia en la NC
TransferenciaAutomaticaNC.Crear(creditNotesNotes, (int)result_creditNotesRepository.Data.DocEntry, _clientFactory, _configuration, _creditNotesRepository);
return resultadoTransaccion.GetInformacionResultado((int)result_creditNotesRepository.Data.DocEntry, result_creditNotesRepository.Data.DocNum.ToString(), "Se registro correctamente...!!!", entidad);
}
}
@@ -598,102 +498,8 @@ namespace Net.Data.WMS.Picking
else
{
// Transferencias automaticas por almacen origen/destino (igual que en DESPACHO)
List<string> ListaUnicaAlmacen = creditNotesNotes.DocumentLines.Select(x => x.WarehouseCode).Distinct().ToList();
List<int> ListDocEntry = new List<int>();
ListaUnicaAlmacen.ForEach(Almacen =>
{
List<string> ListaUnicaAlmDestino = creditNotesNotes.DocumentLines.Where(Linea => Linea.WarehouseCode == Almacen).ToList().Select(x => x.U_ITC_ALMDES).Distinct().ToList().Where(x => !string.IsNullOrEmpty(x)).ToList();
ListaUnicaAlmDestino.ForEach(Destino =>
{
if (Almacen != Destino)
{
BE_StockTransferAutomatico Transfer = new BE_StockTransferAutomatico();
Transfer.FromWarehouse = Almacen;
Transfer.ToWarehouse = Destino;
Transfer.DocDate = creditNotesNotes.DocDate;
Transfer.TaxDate = creditNotesNotes.DocDate;
Transfer.DueDate = creditNotesNotes.DocDueDate;
Transfer.U_SYP_MDTS = "TSI";
Transfer.U_SYP_MDMT = "24";
Transfer.PriceList = -2;
var ListaDetalle_PorAlmacen = creditNotesNotes.DocumentLines.Where(x => x.WarehouseCode == Almacen && x.U_ITC_ALMDES == Destino).ToList();
var ListaUnicaArticulo = ListaDetalle_PorAlmacen.Select(x => x.ItemCode).Distinct().ToList();
Transfer.StockTransferLines = new List<BE_StockTransferLine>();
Transfer.DocumentReferences = new List<BE_StockTransferDocumentReferences>();
ListaUnicaArticulo.ForEach(x =>
{
var ListLote = new List<BE_StockTransferLineBatchNumber>();
// Lotes de todas las lineas del articulo (si el mismo lote esta en varias lineas se suma)
ListaDetalle_PorAlmacen.Where(t => t.ItemCode == x).SelectMany(t => t.BatchNumbers).GroupBy(r => r.BatchNumber).ToList().ForEach(g =>
{
ListLote.Add(new BE_StockTransferLineBatchNumber()
{
BatchNumber = g.Key,
Quantity = g.Sum(r => r.Quantity)
});
});
Transfer.StockTransferLines.Add(new BE_StockTransferLine()
{
ItemCode = x,
ItemDescription = ListaDetalle_PorAlmacen.Where(t => t.ItemCode == x).FirstOrDefault().ItemDescription,
Quantity = Convert.ToDouble(ListaDetalle_PorAlmacen.Where(t => t.ItemCode == x).Sum(t => t.Quantity)),
WarehouseCode = Destino,
FromWarehouseCode = Almacen,
BatchNumbers = ListLote
});
//=== AGREGA DOCUMENTO REFERENCIA
Transfer.DocumentReferences = new List<BE_StockTransferDocumentReferences>
{
new BE_StockTransferDocumentReferences()
{
RefDocEntr = (int)result_creditNotesRepository.Data.DocEntry,
RefObjType = "rot_SalesCreditNote",
IssueDate = DateTime.Now,
Remark = "Nota de Credito",
}
};
});
//=== CREA INSTANCIA PARA CONECTAR A SAP
StockTransferRepository stockTransferRepository = new StockTransferRepository(_clientFactory, _configuration);
var ResultTransfer = stockTransferRepository.StockTransfer(Transfer).Result;
// OJO: si la transferencia falla se ignora (la NC ya esta creada)
if (ResultTransfer.StatusCode == -1)
{
}
else
{
ListDocEntry.Add((int)ResultTransfer.Data.DocEntry);
}
}
});
});
if (ListDocEntry.Count > 0)
{
var listaReferencia = new List<BE_CreditNotesDocumentReferences>();
ListDocEntry.ForEach(x =>
{
listaReferencia.Add(new BE_CreditNotesDocumentReferences()
{
RefDocEntr = x,
IssueDate = DateTime.Now,
RefObjType = "rot_InventoryTransfer",
Remark = "Transferencias Automatica"
});
});
var credit = new
{
DocumentReferences = listaReferencia
};
var Actualizacion = _creditNotesRepository.UpdateCreateCreditNotes(credit, (int)result_creditNotesRepository.Data.DocEntry).Result;
}
// Transferencias de stock automaticas por almacen destino (U_ITC_ALMDES) y su referencia en la NC
TransferenciaAutomaticaNC.Crear(creditNotesNotes, (int)result_creditNotesRepository.Data.DocEntry, _clientFactory, _configuration, _creditNotesRepository);
return resultadoTransaccion.GetInformacionResultado((int)result_creditNotesRepository.Data.DocEntry, result_creditNotesRepository.Data.DocNum.ToString(), "Se registro correctamente...!!!", entidad);
}
}
+3 -96
View File
@@ -537,102 +537,9 @@ namespace Net.Data.WMS.Recibo
}
else
{
// Transferencias por almacen destino (U_ITC_ALMDES). OJO: en Recibo las lineas de la NC no llenan U_ITC_ALMDES, por lo que hoy no se genera ninguna
List<string> ListaUnicaAlmacen = creditNotesNotes.DocumentLines.Select(x => x.WarehouseCode).Distinct().ToList();
List<int> ListDocEntry = new List<int>();
ListaUnicaAlmacen.ForEach(Almacen =>
{
List<string> ListaUnicaAlmDestino = creditNotesNotes.DocumentLines.Where(Linea => Linea.WarehouseCode == Almacen).ToList().Select(x => x.U_ITC_ALMDES).Distinct().ToList().Where(x => !string.IsNullOrEmpty(x)).ToList();
ListaUnicaAlmDestino.ForEach(Destino =>
{
if (Almacen != Destino)
{
BE_StockTransferAutomatico Transfer = new BE_StockTransferAutomatico();
Transfer.FromWarehouse = Almacen;
Transfer.ToWarehouse = Destino;
Transfer.DocDate = creditNotesNotes.DocDate;
Transfer.TaxDate = creditNotesNotes.DocDate;
Transfer.DueDate = creditNotesNotes.DocDueDate;
Transfer.U_SYP_MDTS = "TSI";
Transfer.U_SYP_MDMT = "24";
Transfer.PriceList = -2;
var ListaDetalle_PorAlmacen = creditNotesNotes.DocumentLines.Where(x => x.WarehouseCode == Almacen && x.U_ITC_ALMDES == Destino).ToList();
var ListaUnicaArticulo = ListaDetalle_PorAlmacen.Select(x => x.ItemCode).Distinct().ToList();
Transfer.StockTransferLines = new List<BE_StockTransferLine>();
Transfer.DocumentReferences = new List<BE_StockTransferDocumentReferences>();
ListaUnicaArticulo.ForEach(x =>
{
var ListLote = new List<BE_StockTransferLineBatchNumber>();
// Lotes de todas las lineas del articulo (si el mismo lote esta en varias lineas se suma)
ListaDetalle_PorAlmacen.Where(t => t.ItemCode == x).SelectMany(t => t.BatchNumbers).GroupBy(r => r.BatchNumber).ToList().ForEach(g =>
{
ListLote.Add(new BE_StockTransferLineBatchNumber()
{
BatchNumber = g.Key,
Quantity = g.Sum(r => r.Quantity)
});
});
Transfer.StockTransferLines.Add(new BE_StockTransferLine()
{
ItemCode = x,
ItemDescription = ListaDetalle_PorAlmacen.Where(t => t.ItemCode == x).FirstOrDefault().ItemDescription,
Quantity = Convert.ToDouble(ListaDetalle_PorAlmacen.Where(t => t.ItemCode == x).Sum(t => t.Quantity)),
WarehouseCode = Destino,
FromWarehouseCode = Almacen,
BatchNumbers = ListLote
});
//=== AGREGA DOCUMENTO REFERENCIA
Transfer.DocumentReferences = new List<BE_StockTransferDocumentReferences>
{
new BE_StockTransferDocumentReferences()
{
RefDocEntr = (int)result_creditNotesRepository.Data.DocEntry,
RefObjType = "rot_SalesCreditNote",
IssueDate = DateTime.Now,
Remark = "Nota de Credito",
}
};
});
//=== CREA INSTANCIA PARA CONECTAR A SAP
StockTransferRepository stockTransferRepository = new StockTransferRepository(_clientFactory, _configuration);
var ResultTransfer = stockTransferRepository.StockTransfer(Transfer).Result;
// OJO: si la transferencia falla se ignora (la NC ya esta creada)
if (ResultTransfer.StatusCode == -1)
{
}
else
{
ListDocEntry.Add((int)ResultTransfer.Data.DocEntry);
}
}
});
});
if (ListDocEntry.Count > 0)
{
var listaReferencia = new List<BE_CreditNotesDocumentReferences>();
ListDocEntry.ForEach(x =>
{
listaReferencia.Add(new BE_CreditNotesDocumentReferences()
{
RefDocEntr = x,
IssueDate = DateTime.Now,
RefObjType = "rot_InventoryTransfer",
Remark = "Transferencias Automatica"
});
});
var credit = new
{
DocumentReferences = listaReferencia
};
var Actualizacion = _creditNotesRepository.UpdateCreateCreditNotes(credit, (int)result_creditNotesRepository.Data.DocEntry).Result;
}
// Transferencias de stock automaticas por almacen destino (U_ITC_ALMDES). OJO: en Recibo las lineas de la NC no llenan
// U_ITC_ALMDES, por lo que hoy no se genera ninguna
TransferenciaAutomaticaNC.Crear(creditNotesNotes, (int)result_creditNotesRepository.Data.DocEntry, _clientFactory, _configuration, _creditNotesRepository);
return resultadoTransaccion.GetInformacionResultado((int)result_creditNotesRepository.Data.DocEntry, result_creditNotesRepository.Data.DocNum.ToString(), "Se registro correctamente...!!!", entidad);
}