using Microsoft.Extensions.Configuration; using Net.Business.Entities; using Net.Business.Entities.ServicesLayer.InventoryTransferRequest; using Net.Business.Entities.WMS.SolicitudTransferencia; using Net.Connection.ServiceLayer; using Net.CrossCotting; using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Threading.Tasks; namespace Net.Data.WMS.SolicitudTransferencia { // Modulo 100% nuevo (sin equivalente en el .NET original) - porte 1:1 de // itca_api_sap_wms_python/app/services/solicitud_transferencia_service.py. // Actualiza y cierra documentos InventoryTransferRequests (Solicitud de // Traslado) en SAP Business One via Service Layer. Ver // docs/SOLICITUD_TRANSFERENCIA.md para el detalle completo del contrato. public class SolicitudTransferenciaRepository : ISolicitudTransferenciaRepository { private readonly string _aplicacionName; private readonly IConfiguration _configuration; private readonly IHttpClientFactory _clientFactory; public SolicitudTransferenciaRepository(IHttpClientFactory clientFactory, IConfiguration configuration) { _aplicacionName = GetType().Name; _configuration = configuration; _clientFactory = clientFactory; } // Devuelve null en exito (el caller arma un BE_ResultadoTransaccion 200 con // body - ver el controller; no responde 204 porque muchos clientes HTTP, // incluido HttpClient de .NET, no leen el body de un 204 - ver // docs/SOLICITUD_TRANSFERENCIA.md). // // El PATCH SOLO actualiza cantidades de linea existentes en SAP - no toca // fechas, almacenes ni ningun otro campo del documento - y ELIMINA una // linea cuando Cantidad = 0. Confirmado contra el Service Layer real de QA: // alcanza con mandar LineNum + Quantity por linea junto con el header // B1S-ReplaceCollectionsOnPatch: true, que le indica a Service Layer que // trate StockTransferLines como reemplazo COMPLETO del array, no un merge // parcial. SAP ademas RECHAZA una linea mandada explicita con Quantity: 0, // por eso se omite del array en vez de mandarla en cero. // // Al ser un reemplazo completo, SAP TAMBIEN exige el campo Rate en cada // linea. Se manda Rate: 0.0 fijo (request validado contra SAP); esto pisa // el Rate que tuviera la linea en el documento. No se valida que la linea // exista: si no existe, el error lo devuelve SAP. public async Task> Update(int docEntry, BE_SolicitudTransferenciaPatchRequest entidad) { ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion("Update", _aplicacionName); try { var connectServiceLayer = new ConnectionServiceLayer(_configuration, _clientFactory); var lines = new List(); foreach (var detalle in entidad.Detalle ?? new List()) { if (detalle.Cantidad == 0) continue; lines.Add(new { LineNum = detalle.Linea, Quantity = detalle.Cantidad, Rate = 0.0 }); } await connectServiceLayer.PatchNoContentAsync( $"InventoryTransferRequests({docEntry})", new { StockTransferLines = lines }, new Dictionary { ["B1S-ReplaceCollectionsOnPatch"] = "true" }); return null; } catch (Exception ex) { return resultadoTransaccion.GetInformacionResultado(ex.Message.ToString(), (object)entidad); } } // Cierra el documento completo. Funcionalidad nueva (no existe en el .NET // original) - SAP Service Layer cierra documentos via POST a la sub-ruta // /Close, mismo patron que Picking/HojaRuta/Cerrar. Devuelve null en exito // (el caller arma el BE_ResultadoTransaccion 200 con body). public async Task> Cerrar(int docEntry) { ResultadoTransaccion resultadoTransaccion = new ResultadoTransaccion("Cerrar", _aplicacionName); try { var connectServiceLayer = new ConnectionServiceLayer(_configuration, _clientFactory); await connectServiceLayer.PostActionAsync($"InventoryTransferRequests({docEntry})/Close"); return null; } catch (Exception ex) { return resultadoTransaccion.GetInformacionResultado(ex.Message.ToString(), (object)null); } } } }