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>
656 lines
40 KiB
C#
656 lines
40 KiB
C#
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.Logging.Abstractions;
|
|
using Net.Business.Entities;
|
|
using Net.Business.Entities.ServicesLayer;
|
|
using Net.Business.Entities.ServicesLayer.CreditNotes;
|
|
using Net.Business.Entities.ServicesLayer.InventoryGenEntries;
|
|
using Net.Business.Entities.ServicesLayer.InventoryGenExits;
|
|
using Net.Business.Entities.ServicesLayer.Invoices;
|
|
using Net.Business.Entities.ServicesLayer.Items;
|
|
using Net.Business.Entities.ServicesLayer.ReturnRequest;
|
|
using Net.Business.Entities.ServicesLayer.StockTransfer;
|
|
using Net.Business.Entities.WMS.HojaRuta;
|
|
using Net.Business.Entities.WMS.Picking;
|
|
using Net.Business.Entities.WMS.ProcesoPicking;
|
|
using Net.Connection;
|
|
using Net.Connection.ServiceLayer;
|
|
using Net.CrossCotting;
|
|
using Net.Data.HelperData.Correlativo;
|
|
using Net.Data.HelperData.HelperProcesoPermitido;
|
|
using Net.Data.HelperData.Stock;
|
|
using Net.Data.ServicesLayer;
|
|
using Net.Data.ServicesLayer.CreditNotes;
|
|
using Net.Data.ServicesLayer.GlobalData;
|
|
using Net.Data.ServicesLayer.InventoryGenExits;
|
|
using Net.Data.ServicesLayer.ReturnRequest;
|
|
using Net.Data.ServicesLayer.StockTransfer;
|
|
using Sap.Data.Hana;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Net.Http;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Net.Data.WMS.Picking
|
|
{
|
|
public class PickingRepository : RepositoryBase<object>, IPickingRepository
|
|
{
|
|
#region Variables Globales
|
|
private string _aplicacionName;
|
|
private string _metodoName;
|
|
private readonly Regex regex = new Regex(@"<(\w+)>.*");
|
|
|
|
private readonly IHttpClientFactory _clientFactory;
|
|
private readonly IConfiguration _configuration;
|
|
#endregion
|
|
|
|
public PickingRepository(IConnectionSQL context, IHttpClientFactory clientFactory, IConfiguration configuration) : base(context)
|
|
{
|
|
_clientFactory = clientFactory;
|
|
_configuration = configuration;
|
|
_aplicacionName = GetType().Name;
|
|
}
|
|
|
|
// POST /api/Picking: actualiza el estado de la factura en HANA y, segun Proceso + IdEstadoCubico, genera documentos en SAP:
|
|
// DESPACHO (estado 5/6) -> NC por lo no entregado + transferencias a los almacenes destino (U_ITC_ALMDES)
|
|
// PICKING (estado 13) -> NC con un lote nuevo por linea + transferencias
|
|
// ULTIMA MILLA (estado 23, solo con Notificacion = "cierre") -> Solicitud de Devolucion
|
|
public async Task<BE_ResultadoTransaccion<object>> Create(BE_PickingRequest entidad)
|
|
{
|
|
_metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString();
|
|
|
|
ResultadoTransaccion<object> resultadoTransaccion = new ResultadoTransaccion<object>(_metodoName, _aplicacionName);
|
|
|
|
if (entidad.DocEntry == 0)
|
|
{
|
|
return resultadoTransaccion.GetInformacionResultado("El campo docEntry no puede ser cero o vacio", entidad);
|
|
}
|
|
|
|
return await Task.Run(() =>
|
|
{
|
|
try
|
|
{
|
|
// Datos del motivo (@SYP_MOTIVOS): almacen destino, si es reproceso y tipo/descripcion de la NC
|
|
var Almacen = HelperProcesoPermitido.GetMotivoAlmacen(entidad.CodMotivo, out bool Reproceso, out string MotivoNotaCredito, out string DescripcionMotivo);
|
|
|
|
if (string.IsNullOrEmpty(entidad.Proceso))
|
|
{
|
|
return resultadoTransaccion.GetInformacionResultado("SAP: Se necesita definir el proceso para continuar con el proceso.", entidad);
|
|
}
|
|
|
|
if (entidad.IdEstadoCubico == 0)
|
|
{
|
|
return resultadoTransaccion.GetInformacionResultado("SAP: Se necesita indicar el IdEstado Cubico para continuar con el proceso.", entidad);
|
|
}
|
|
|
|
int Existe = HelperProcesoPermitido.Get(entidad.Proceso, entidad.IdEstadoCubico, "PICKING", out List<BE_ProcesoPicking> ListaProceso);
|
|
var Proceso = ListaProceso.FirstOrDefault();
|
|
if (Existe == 0)
|
|
{
|
|
return resultadoTransaccion.GetInformacionResultado("El Proceso y estado no se encuentra configurado para este EndPoint", entidad);
|
|
}
|
|
|
|
var TotalDetalle = 0;
|
|
var TotalDetalle_Anulado = 0;
|
|
var TotalDetalle_Completo = 0;
|
|
if (Existe > 1)
|
|
{
|
|
TotalDetalle = entidad.Detalle.Count();
|
|
TotalDetalle_Anulado = entidad.Detalle.Where(x=> x.Estado == "A").Count();
|
|
TotalDetalle_Completo = entidad.Detalle.Where(x => x.Estado == "C").Count();
|
|
if(TotalDetalle == TotalDetalle_Anulado)
|
|
{
|
|
Proceso = ListaProceso.FirstOrDefault(x => x.Code == "013");
|
|
if (Reproceso)
|
|
{
|
|
Proceso = ListaProceso.FirstOrDefault(x => x.Code == "017");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Proceso = ListaProceso.FirstOrDefault(x => x.Code == "012");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TotalDetalle = entidad.Detalle.Count();
|
|
TotalDetalle_Anulado = entidad.Detalle.Where(x => x.Estado == "A").Count();
|
|
TotalDetalle_Completo = entidad.Detalle.Where(x => x.Estado == "C").Count();
|
|
}
|
|
|
|
//=== REALIZA PROCESO COMPLETO DE ACTUALIZACION
|
|
HelperProcesoPiciking.Set(entidad.Proceso, entidad.IdEstadoCubico, entidad.DocEntry, entidad.CodMotivo, Proceso.Code);
|
|
|
|
// === Solo para el proceso "ULTIMA MILLA": "notificacion" distinta de "cierre"
|
|
// (o ausente) es la notificacion preliminar en tiempo real - solo actualiza
|
|
// estado en HANA (ya hecho arriba), NUNCA debe crear documentos en SAP.
|
|
// DESPACHO, PICKING y demas procesos no dependen de este campo.
|
|
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);
|
|
}
|
|
// Todas las lineas completas: no hay nada que devolver (el tipo de documento 9 sigue el flujo)
|
|
if(TotalDetalle == TotalDetalle_Completo && entidad.IdTipoDoc != 9)
|
|
{
|
|
return resultadoTransaccion.GetInformacionResultado(entidad.DocEntry, entidad.NumOrden, "Se registro correctamente...!!!", entidad);
|
|
}
|
|
|
|
#region PROCESO DE NOTA DE CREDITO
|
|
|
|
// DESPACHO (estado 5 o 6): NC desde la factura; no aplica para IdTipoDoc 9
|
|
if (entidad.Proceso.ToUpper() == "DESPACHO" && (entidad.IdEstadoCubico == 6 || entidad.IdEstadoCubico == 5))
|
|
{
|
|
if (entidad.IdTipoDoc != 9)
|
|
{
|
|
CreditNotesRepository _creditNotesRepository = new CreditNotesRepository(_clientFactory, _configuration, context);
|
|
BE_CreditNotesNotes creditNotesNotes = new BE_CreditNotesNotes
|
|
{
|
|
DocObjectCode = "oCreditNotes",
|
|
DocumentLines = new List<BE_CreditNotesLine>()
|
|
};
|
|
|
|
InvoiceRepository invoicestRepository = new InvoiceRepository(_clientFactory, _configuration, context);
|
|
BE_ResultadoTransaccion<BE_InvoicesConsulta> response_invoicesRepository = invoicestRepository.GetInvoice(entidad.DocEntry).Result;
|
|
|
|
if (response_invoicesRepository.DocEntry == -1)
|
|
{
|
|
return resultadoTransaccion.GetInformacionResultado("SAP: La Factura no se encuentra", entidad);
|
|
}
|
|
|
|
|
|
BE_InvoicesConsulta _invoices = response_invoicesRepository.ListData.FirstOrDefault();
|
|
|
|
if (_invoices.DocumentStatus != "bost_Open")
|
|
{
|
|
var Response_Reopen = invoicestRepository.ReOpen(_invoices.DocEntry).Result;
|
|
if (Response_Reopen.DocEntry == -1)
|
|
{
|
|
return resultadoTransaccion.GetInformacionResultado("SAP: La Factura no se puede reabrir. " + Response_Reopen.Message, entidad);
|
|
}
|
|
}
|
|
|
|
// Serie de la NC segun el TIPO de documento de la factura (U_SYP_MDTD): 03 = boleta -> BC10, otro -> FC10.
|
|
// El correlativo sale de @SYP_NUMDOC (HelperCorrelativo)
|
|
string Serie = _invoices.U_SYP_MDTD == "03" ? "BC10" : "FC10";
|
|
string Correlativo = HelperCorrelativo.Get(Serie);
|
|
creditNotesNotes.DocCurrency = _invoices.DocCurrency;
|
|
creditNotesNotes.CardCode = _invoices.CardCode;
|
|
creditNotesNotes.CardName = _invoices.CardName;
|
|
creditNotesNotes.PaymentGroupCode = _invoices.PaymentGroupCode;
|
|
creditNotesNotes.DocDate = DateTime.Now;
|
|
creditNotesNotes.DocDueDate = DateTime.Now;
|
|
creditNotesNotes.U_SYP_MDTO = _invoices.U_SYP_MDTD;
|
|
creditNotesNotes.U_SYP_MDCO = _invoices.U_SYP_MDCD;
|
|
creditNotesNotes.U_SYP_MDSO = _invoices.U_SYP_MDSD;
|
|
creditNotesNotes.U_SYP_MOTNC = DescripcionMotivo;
|
|
creditNotesNotes.U_SYP_TPONC = MotivoNotaCredito;
|
|
creditNotesNotes.U_SYP_MDCD = Correlativo;
|
|
creditNotesNotes.U_SYP_MDSD = Serie;
|
|
creditNotesNotes.U_SYP_MDTD = "07";
|
|
creditNotesNotes.U_SYP_FECHAREF = _invoices.DocDate.ToString("yyyy-MM-dd");
|
|
creditNotesNotes.NumAtCard = ("07-" + Serie + "-" + Correlativo);
|
|
|
|
entidad.Detalle.ForEach(x =>
|
|
{
|
|
var Item = _invoices.DocumentLines.ToList().FirstOrDefault(t => t.LineNum == x.Item);
|
|
if (Item != null)
|
|
{
|
|
if (Item.Quantity - x.CantidadPedida > 0)
|
|
{
|
|
creditNotesNotes.DocumentLines.Add(new BE_CreditNotesLine()
|
|
{
|
|
Currency = _invoices.DocCurrency,
|
|
BatchNumbers = new List<BE_CreditNotesBatchNumbers>(),
|
|
ItemCode = Item.ItemCode,
|
|
ItemDescription = Item.ItemDescription,
|
|
PriceAfterVAT = Item.PriceAfterVAT,
|
|
Quantity = Item.Quantity - x.CantidadPedida,
|
|
WarehouseCode = Item.WarehouseCode,
|
|
BaseEntry = entidad.DocEntry,
|
|
BaseLine = x.Item,
|
|
BaseType = 13,
|
|
LineNum = x.Item,
|
|
U_ITC_ALMDES = ((Almacen == "ALMPRO") ? Item.WarehouseCode : Almacen),
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
// == REALIZA DISTRIBUCION DE STOCK POR LOTE / ALMACEN
|
|
// Linea por linea: si la factura tiene una Entrega (BaseType 15) como documento
|
|
// origen, los lotes salen de la linea de esa Entrega (BaseLine); si no, de la
|
|
// propia linea de la factura (LineNum).
|
|
var Entregas = new Dictionary<int, BE_DeliveryNotesConsulta>();
|
|
var ErroresLote = new List<string>();
|
|
creditNotesNotes.DocumentLines.ForEach(line =>
|
|
{
|
|
#region CONSULTA A HANA
|
|
|
|
//List<BE_ItemStock> ListaStock = HelperStock.Get(line.ItemCode, entidad.CodigoAlmacen);
|
|
var ReferenciaFactura = _invoices.DocumentLines.FirstOrDefault(t => t.LineNum == line.LineNum);
|
|
List<BE_InvoicesBatchNumbers> ListaStock;
|
|
|
|
if (ReferenciaFactura.BaseType == 15 && ReferenciaFactura.BaseEntry.HasValue && ReferenciaFactura.BaseLine.HasValue)
|
|
{
|
|
int DocEntryEntrega = ReferenciaFactura.BaseEntry.Value;
|
|
if (!Entregas.TryGetValue(DocEntryEntrega, out BE_DeliveryNotesConsulta Entrega))
|
|
{
|
|
var response_entrega = invoicestRepository.GetDeliveryNote(DocEntryEntrega).Result;
|
|
Entrega = (response_entrega.DocEntry == -1) ? null : response_entrega.ListData?.FirstOrDefault();
|
|
Entregas[DocEntryEntrega] = Entrega;
|
|
}
|
|
|
|
if (Entrega == null)
|
|
{
|
|
ErroresLote.Add($"Linea {line.LineNum} ({line.ItemCode}): no se pudo leer la Entrega {DocEntryEntrega} origen de la factura");
|
|
return;
|
|
}
|
|
|
|
var LineaEntrega = Entrega.DocumentLines?.FirstOrDefault(t => t.LineNum == ReferenciaFactura.BaseLine.Value);
|
|
ListaStock = LineaEntrega?.BatchNumbers ?? new List<BE_InvoicesBatchNumbers>();
|
|
}
|
|
else
|
|
{
|
|
ListaStock = ReferenciaFactura.BatchNumbers ?? new List<BE_InvoicesBatchNumbers>();
|
|
}
|
|
|
|
double CantidadPendiente = (double)line.Quantity;
|
|
var ListOrdenadaFecha = ListaStock;
|
|
ListOrdenadaFecha.ForEach(Lote =>
|
|
{
|
|
if (CantidadPendiente > 0)
|
|
{
|
|
if (Lote.Quantity >= CantidadPendiente)
|
|
{
|
|
line.BatchNumbers.Add(new BE_CreditNotesBatchNumbers() { BatchNumber = Lote.BatchNumber, Quantity = CantidadPendiente });
|
|
CantidadPendiente = 0;
|
|
}
|
|
else if (Lote.Quantity < CantidadPendiente)
|
|
{
|
|
line.BatchNumbers.Add(new BE_CreditNotesBatchNumbers() { BatchNumber = Lote.BatchNumber, Quantity = Lote.Quantity });
|
|
CantidadPendiente -= Lote.Quantity;
|
|
}
|
|
}
|
|
});
|
|
|
|
// Hay lotes de origen pero no alcanzan para la cantidad a devolver
|
|
if (ListaStock.Count > 0 && CantidadPendiente > 0.000001)
|
|
{
|
|
ErroresLote.Add($"Linea {line.LineNum} ({line.ItemCode}): los lotes de origen no cubren la cantidad {line.Quantity} (faltan {CantidadPendiente})");
|
|
}
|
|
|
|
#endregion
|
|
});
|
|
|
|
if (ErroresLote.Count > 0)
|
|
{
|
|
return resultadoTransaccion.GetInformacionResultado("SAP: No se pudo asignar lotes a la nota de credito. " + string.Join(" | ", ErroresLote), entidad);
|
|
}
|
|
|
|
if (creditNotesNotes.DocumentLines.Count > 0)
|
|
{
|
|
var result_creditNotesRepository = _creditNotesRepository.SetCreateCreditNotes(creditNotesNotes).Result;
|
|
|
|
if (result_creditNotesRepository.StatusCode == -1)
|
|
{
|
|
return resultadoTransaccion.GetInformacionResultado(result_creditNotesRepository.Message.ToString(), entidad);
|
|
}
|
|
else
|
|
{
|
|
// 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);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return resultadoTransaccion.GetInformacionResultado((int)entidad.DocEntry, entidad.NumOrden.ToString(), "Se registro correctamente...!!!", entidad);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//=== ASIGNA PRECIO PROMEDIO
|
|
foreach (var x in entidad.Detalle)
|
|
{
|
|
var Stock = HelperStock.GetConsolidado(x.CodigoArticulo, entidad.CodigoAlmacen);
|
|
if (Stock.Count == 0)
|
|
{
|
|
return resultadoTransaccion.GetInformacionResultado("No existe stock disponible para el articulo " + x.CodigoArticulo, entidad);
|
|
}
|
|
x.PrecioPromedio = Stock.FirstOrDefault().AvgPrice;
|
|
};
|
|
|
|
GlobalDataRepository globalDataRepository = new GlobalDataRepository(_clientFactory, _configuration, context);
|
|
|
|
var Data_SolicitudSalida = globalDataRepository.GetSolicitudSalida(entidad.DocEntry).Result.ListData.FirstOrDefault();
|
|
|
|
InventoryGenExitsRepository inventoryGenExitsRepository = new InventoryGenExitsRepository(_clientFactory, _configuration, context);
|
|
BE_InventoryGenExits _InventoryGenExits = new BE_InventoryGenExits()
|
|
{
|
|
DocObjectCode = "oInventoryGenExit",
|
|
DocDate = DateTime.Now,
|
|
DocDueDate = DateTime.Now,
|
|
PaymentGroupCode = "-2",
|
|
DocCurrency = "S/",
|
|
DocRate = 1,
|
|
DocumentLines = new List<BE_InventoryGenExitsLine>(),
|
|
U_SYP_TPOSALME = Data_SolicitudSalida.U_ITC_MDTS,
|
|
U_ITC_WMS_NUMINV = "",
|
|
U_ARD_PERSOLIC = Data_SolicitudSalida.U_ITC_USRSOL,
|
|
Comments = Data_SolicitudSalida.U_ITC_MDCM
|
|
};
|
|
|
|
int LineNum = 0;
|
|
entidad.Detalle.ForEach(detalle =>
|
|
{
|
|
_InventoryGenExits.DocumentLines.Add(new BE_InventoryGenExitsLine()
|
|
{
|
|
Currency = "S/",
|
|
ItemCode = detalle.CodigoArticulo,
|
|
ItemDescription = Data_SolicitudSalida.ITCA_SOLSALMERDETCollection.FirstOrDefault(item_s => item_s.LineId == detalle.Item).U_ITC_ItemName,
|
|
Quantity = (double)detalle.CantidadPedida,
|
|
LineNum = LineNum,
|
|
PriceAfterVAT = detalle.PrecioPromedio,
|
|
LineTotal = detalle.PrecioPromedio * (double)detalle.CantidadPedida,
|
|
WarehouseCode = entidad.CodigoAlmacen,
|
|
AccountCode = Data_SolicitudSalida.ITCA_SOLSALMERDETCollection.FirstOrDefault(item_s => item_s.LineId == detalle.Item).U_ITC_AccCode,
|
|
BatchNumbers = new List<BE_InventoryGenExitsBatchNumbers>(),
|
|
CostingCode = Data_SolicitudSalida.ITCA_SOLSALMERDETCollection.FirstOrDefault(item_s => item_s.LineId == detalle.Item).U_ITC_CCOST,
|
|
});
|
|
|
|
LineNum++;
|
|
});
|
|
|
|
|
|
_InventoryGenExits.DocumentLines.ForEach(line =>
|
|
{
|
|
#region CONSULTA A HANA
|
|
|
|
List<BE_ItemStock> ListaStock = HelperStock.Get(line.ItemCode, entidad.CodigoAlmacen);
|
|
var CantidadPendiente = line.Quantity;
|
|
var ListOrdenadaFecha = ListaStock.OrderBy(x => x.ExpDate).ToList();
|
|
var cantidadStock = ListaStock.Sum(x => x.OnHandQty);
|
|
if (cantidadStock < line.Quantity)
|
|
{
|
|
throw new Exception($"El producto {line.ItemCode} no cuenta con stock suficiente");
|
|
}
|
|
else
|
|
{
|
|
ListOrdenadaFecha.ForEach(Lote =>
|
|
{
|
|
if (CantidadPendiente > 0)
|
|
{
|
|
if (Lote.OnHandQty >= CantidadPendiente)
|
|
{
|
|
line.BatchNumbers.Add(new BE_InventoryGenExitsBatchNumbers() { BatchNumber = Lote.DistNumber, Quantity = CantidadPendiente });
|
|
CantidadPendiente = 0;
|
|
}
|
|
else if (Lote.OnHandQty < CantidadPendiente)
|
|
{
|
|
line.BatchNumbers.Add(new BE_InventoryGenExitsBatchNumbers() { BatchNumber = Lote.DistNumber, Quantity = Lote.OnHandQty });
|
|
CantidadPendiente -= Lote.OnHandQty;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
#endregion
|
|
});
|
|
|
|
var Result = inventoryGenExitsRepository.SetCreateInventoryGenExits(_InventoryGenExits, false).Result;
|
|
if (Result.StatusCode == -1)
|
|
{
|
|
return resultadoTransaccion.GetInformacionResultado(Result.Message.ToString(), entidad);
|
|
}
|
|
|
|
return resultadoTransaccion.GetInformacionResultado((int)entidad.DocEntry, entidad.NumOrden.ToString(), "Se registro correctamente...!!!", entidad);
|
|
}
|
|
}
|
|
|
|
// PICKING (estado 13): NC con un lote nuevo (fecha y hora) por linea, sin usar los lotes de la factura; solo lineas con diferencia
|
|
if (entidad.Proceso.ToUpper() == "PICKING" && entidad.IdEstadoCubico == 13)
|
|
{
|
|
CreditNotesRepository _creditNotesRepository = new CreditNotesRepository(_clientFactory, _configuration, context);
|
|
BE_CreditNotesNotes creditNotesNotes = new BE_CreditNotesNotes
|
|
{
|
|
DocObjectCode = "oCreditNotes",
|
|
DocumentLines = new List<BE_CreditNotesLine>()
|
|
};
|
|
|
|
InvoiceRepository invoicestRepository = new InvoiceRepository(_clientFactory, _configuration, context);
|
|
BE_ResultadoTransaccion<BE_InvoicesConsulta> response_invoicesRepository = invoicestRepository.GetInvoice(entidad.DocEntry).Result;
|
|
|
|
if (response_invoicesRepository.DocEntry == -1)
|
|
{
|
|
return resultadoTransaccion.GetInformacionResultado("SAP: La Factura no se encuentra", entidad);
|
|
}
|
|
BE_InvoicesConsulta _invoices = response_invoicesRepository.ListData.FirstOrDefault();
|
|
|
|
if (_invoices.DocumentStatus != "bost_Open")
|
|
{
|
|
var Response_Reopen = invoicestRepository.ReOpen(_invoices.DocEntry).Result;
|
|
if (Response_Reopen.DocEntry == -1)
|
|
{
|
|
return resultadoTransaccion.GetInformacionResultado("SAP: La Factura no se puede reabrir. " + Response_Reopen.Message, entidad);
|
|
}
|
|
}
|
|
|
|
// Serie segun el tipo de documento de la factura (03 = boleta -> BC10, otro -> FC10)
|
|
string Serie = _invoices.U_SYP_MDTD == "03" ? "BC10" : "FC10";
|
|
string Correlativo = HelperCorrelativo.Get(Serie);
|
|
|
|
creditNotesNotes.DocCurrency = _invoices.DocCurrency;
|
|
creditNotesNotes.CardCode = _invoices.CardCode;
|
|
creditNotesNotes.CardName = _invoices.CardName;
|
|
creditNotesNotes.PaymentGroupCode = _invoices.PaymentGroupCode;
|
|
creditNotesNotes.DocDate = DateTime.Now;
|
|
creditNotesNotes.DocDueDate = DateTime.Now;
|
|
creditNotesNotes.U_SYP_MDTO = _invoices.U_SYP_MDTD;
|
|
creditNotesNotes.U_SYP_MDCO = _invoices.U_SYP_MDCD;
|
|
creditNotesNotes.U_SYP_MDSO = _invoices.U_SYP_MDSD;
|
|
creditNotesNotes.U_SYP_MOTNC = DescripcionMotivo;
|
|
creditNotesNotes.U_SYP_TPONC = MotivoNotaCredito;
|
|
creditNotesNotes.U_SYP_MDCD = Correlativo;
|
|
creditNotesNotes.U_SYP_MDSD = Serie;
|
|
creditNotesNotes.U_SYP_MDTD = "07";
|
|
creditNotesNotes.U_SYP_FECHAREF = _invoices.DocDate.ToString("yyyy-MM-dd");
|
|
creditNotesNotes.NumAtCard = ("07-" + Serie+ "-" + Correlativo);
|
|
|
|
entidad.Detalle.ForEach(x =>
|
|
{
|
|
var Item = _invoices.DocumentLines.ToList().FirstOrDefault(t => t.LineNum == x.Item);
|
|
// Solo lineas con diferencia a devolver (igual que DESPACHO): una linea completa daria cantidad 0
|
|
if (Item != null && Item.Quantity - x.CantidadPedida > 0)
|
|
{
|
|
creditNotesNotes.DocumentLines.Add(new BE_CreditNotesLine()
|
|
{
|
|
Currency = _invoices.DocCurrency,
|
|
BatchNumbers = new List<BE_CreditNotesBatchNumbers>(),
|
|
ItemCode = Item.ItemCode,
|
|
ItemDescription = Item.ItemDescription,
|
|
PriceAfterVAT = Item.PriceAfterVAT,
|
|
Quantity = Item.Quantity - x.CantidadPedida,
|
|
WarehouseCode = Item.WarehouseCode,
|
|
BaseEntry = entidad.DocEntry,
|
|
BaseLine = x.Item,
|
|
BaseType = 13,
|
|
LineNum = x.Item,
|
|
U_ITC_ALMDES = ((Almacen == "ALMPRO") ? Item.WarehouseCode : Almacen),
|
|
});
|
|
}
|
|
});
|
|
|
|
creditNotesNotes.DocumentLines.ForEach(line =>
|
|
{
|
|
|
|
line.BatchNumbers.Add(new BE_CreditNotesBatchNumbers() { BatchNumber = DateTime.Now.ToString("yyyyMMddhhmmss"), Quantity = (double)line.Quantity });
|
|
});
|
|
|
|
if (creditNotesNotes.DocumentLines.Count > 0)
|
|
{
|
|
var result_creditNotesRepository = _creditNotesRepository.SetCreateCreditNotes(creditNotesNotes).Result;
|
|
if (result_creditNotesRepository.StatusCode == -1)
|
|
{
|
|
return resultadoTransaccion.GetInformacionResultado(result_creditNotesRepository.Message.ToString(), entidad);
|
|
}
|
|
else
|
|
{
|
|
|
|
// 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);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return resultadoTransaccion.GetInformacionResultado((int)entidad.DocEntry, entidad.NumOrden.ToString(), "Se registro correctamente...!!!", entidad);
|
|
}
|
|
}
|
|
// ULTIMA MILLA (estado 23): con Notificacion = "cierre" (el filtro esta arriba) y el proceso configurado como SOLICITUD DEV,
|
|
// crea la Solicitud de Devolucion con lo no entregado; no genera NC ni transferencias
|
|
if(entidad.Proceso.ToUpper() == "ULTIMA MILLA" && entidad.IdEstadoCubico == 23)
|
|
{
|
|
if(Proceso.U_ITCA_GNRPROC == "SOLICITUD DEV" && !Reproceso)
|
|
{
|
|
|
|
if (string.IsNullOrEmpty(Almacen))
|
|
{
|
|
return resultadoTransaccion.GetInformacionResultado("El motivo no tiene asignado un almacen de destino", entidad);
|
|
}
|
|
|
|
ReturnRequestRepository returnRequestRepository = new ReturnRequestRepository(_clientFactory, _configuration);
|
|
|
|
InvoiceRepository invoicestRepository = new InvoiceRepository(_clientFactory, _configuration, context);
|
|
BE_ResultadoTransaccion<BE_InvoicesConsulta> response_invoicesRepository = invoicestRepository.GetInvoice(entidad.DocEntry).Result;
|
|
|
|
if (response_invoicesRepository.DocEntry == -1)
|
|
{
|
|
return resultadoTransaccion.GetInformacionResultado("SAP: La Factura no se encuentra", entidad);
|
|
}
|
|
BE_InvoicesConsulta invoices = response_invoicesRepository.ListData.FirstOrDefault();
|
|
BE_ReturnRequest _ReturnRequest = new BE_ReturnRequest()
|
|
{
|
|
CardCode = invoices.CardCode,
|
|
CardName = invoices.CardName,
|
|
DocCurrency = invoices.DocCurrency,
|
|
DocDate = DateTime.Now,
|
|
DocDueDate = DateTime.Now,
|
|
DocObjectCode = "oReturnRequest",
|
|
PaymentGroupCode = invoices.PaymentGroupCode,
|
|
U_SYP_MOTNC = DescripcionMotivo,
|
|
U_SYP_TPONC = MotivoNotaCredito,
|
|
U_SYP_MDTO = invoices.U_SYP_MDTD,
|
|
U_SYP_MDCO = invoices.U_SYP_MDCD,
|
|
U_SYP_MDSO = invoices.U_SYP_MDSD,
|
|
U_SYP_FECHAREF = invoices.DocDate,
|
|
DocumentLines = new List<BE_ReturnRequestLine>()
|
|
};
|
|
|
|
var ListaDetalle = entidad.Detalle.Where(x => x.Estado != "C").ToList();
|
|
ListaDetalle.ForEach(detalle =>
|
|
{
|
|
var Detalle_Factura = invoices.DocumentLines.FirstOrDefault(x => x.LineNum == detalle.Item);
|
|
_ReturnRequest.DocumentLines.Add(new BE_ReturnRequestLine()
|
|
{
|
|
LineNum = detalle.Item,
|
|
BaseEntry = entidad.DocEntry,
|
|
BaseLine = Detalle_Factura.LineNum,
|
|
BatchNumbers = new List<BE_ReturnRequestBatchNumbers>(),
|
|
Currency = invoices.DocCurrency,
|
|
ItemCode = Detalle_Factura.ItemCode,
|
|
ItemDescription = Detalle_Factura.ItemDescription,
|
|
PriceAfterVAT = Detalle_Factura.PriceAfterVAT,
|
|
Quantity = (Detalle_Factura.Quantity - detalle.CantidadPedida),
|
|
WarehouseCode = Detalle_Factura.WarehouseCode,
|
|
BaseType = 13,
|
|
U_ITC_ALMDES = ((Almacen == "ALMPRO") ? Detalle_Factura.WarehouseCode: Almacen),
|
|
});
|
|
});
|
|
|
|
var _returnRequestRepository_Result = returnRequestRepository.SetCreateReturnRequest(_ReturnRequest).Result;
|
|
if (_returnRequestRepository_Result.StatusCode == -1)
|
|
{
|
|
return resultadoTransaccion.GetInformacionResultado(_returnRequestRepository_Result.Message.ToString(), entidad);
|
|
}
|
|
|
|
return resultadoTransaccion.GetInformacionResultado((int)_returnRequestRepository_Result.Data.DocEntry, _returnRequestRepository_Result.Data.DocNum.ToString(), "Se registro correctamente...!!!", entidad);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
return resultadoTransaccion.GetInformacionResultado(entidad.DocEntry, entidad.NumOrden, "Registrado Correctamente", entidad);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return resultadoTransaccion.GetInformacionResultado(ex.Message.ToString(), entidad);
|
|
}
|
|
});
|
|
}
|
|
|
|
// POST /api/Picking/ruta: registra el estado de la hoja de ruta (inicio/fin de ruta) en HANA; no crea documentos en SAP
|
|
public async Task<BE_ResultadoTransaccion<object>> CreateHojaRuta(BE_HojaRutaEntities entidad)
|
|
{
|
|
_metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString();
|
|
|
|
ResultadoTransaccion<object> resultadoTransaccion = new ResultadoTransaccion<object>(_metodoName, _aplicacionName);
|
|
|
|
if (entidad.DocEntry == 0)
|
|
{
|
|
return resultadoTransaccion.GetInformacionResultado("El campo docEntry no puede ser cero o vacio", entidad);
|
|
}
|
|
|
|
return await Task.Run(() =>
|
|
{
|
|
try
|
|
{
|
|
if (string.IsNullOrEmpty(entidad.Proceso))
|
|
{
|
|
return resultadoTransaccion.GetInformacionResultado("SAP: Se necesita definir el proceso para continuar con el proceso.", entidad);
|
|
}
|
|
|
|
if (entidad.IdEstadoCubico == 0)
|
|
{
|
|
return resultadoTransaccion.GetInformacionResultado("SAP: Se necesita indicar el IdEstado Cubico para continuar con el proceso.", entidad);
|
|
}
|
|
|
|
int Existe = HelperProcesoPermitido.Get(entidad.Proceso, entidad.IdEstadoCubico, "HOJARUTA", out List<BE_ProcesoPicking> ListaProceso);
|
|
if (Existe == 0)
|
|
{
|
|
return resultadoTransaccion.GetInformacionResultado("El Proceso y estado no se encuentra configurado para este EndPoint", entidad);
|
|
}
|
|
|
|
HelperProcesoPiciking.Set(entidad.Proceso, entidad.IdEstadoCubico, entidad.DocEntry, HelperProcesoPermitido.ConvertTimeToInteger(entidad.HoraInicio), HelperProcesoPermitido.ConvertTimeToInteger(entidad.FinRuta), entidad.CodMotivo, ListaProceso.FirstOrDefault().Code);
|
|
return resultadoTransaccion.GetInformacionResultado(entidad.DocEntry, entidad.DocEntry.ToString(), "Registrado Correctamente", entidad);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return resultadoTransaccion.GetInformacionResultado(ex.Message.ToString(), entidad);
|
|
}
|
|
});
|
|
}
|
|
|
|
// POST /api/Picking/HojaRuta/{docEntry}/Cerrar: cierra el UDO ARD_PHR en SAP (se llama una sola vez al terminar la ruta)
|
|
public async Task<BE_ResultadoTransaccion<object>> CerrarHojaRuta(int docEntry)
|
|
{
|
|
_metodoName = "CerrarHojaRuta";
|
|
ResultadoTransaccion<object> resultadoTransaccion = new ResultadoTransaccion<object>(_metodoName, _aplicacionName);
|
|
|
|
try
|
|
{
|
|
// Hoja de Ruta es un UDO en SAP (ARD_PHR) - mismo patron que
|
|
// SolicitudTransferencia/{docEntry}/cerrar (POST {recurso}({docEntry})/Close).
|
|
var connectServiceLayer = new ConnectionServiceLayer(_configuration, _clientFactory);
|
|
await connectServiceLayer.PostActionAsync($"ARD_PHR({docEntry})/Close");
|
|
return resultadoTransaccion.GetInformacionResultado(docEntry, docEntry.ToString(), "Cerrado Correctamente", (object)null);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return resultadoTransaccion.GetInformacionResultado(ex.Message.ToString(), (object)null);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|