Compare commits

..
2 Commits
Author SHA1 Message Date
GeorgeandClaude Sonnet 5.5 a5a4160471 Limpieza: comentarios en el codigo, if vacio de CreateHojaRuta y documentacion. Versión 2.1.8.0
Sin cambios de comportamiento. Comentarios en Picking, Recibo,
ConnectionServiceLayer, CreditNotesRepository, InvoiceRepository y
RepositoryWrapper.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-14 19:31:06 -05:00
GeorgeandClaude Sonnet 5.5 57b4578f1f Limpieza: quitar codigo sin uso (metodos sin llamadores, throw inalcanzable, variables y propiedades del RepositoryWrapper sin uso)
- ConnectionServiceLayer: ValidarCertificado, Logout, CancelAsyncSBA, DeleteAsyncSBA y throw inalcanzable en PatchAsyncSBA
- HelperDB (SET ejecutaba SQL arbitrario, sin llamadores)
- RepositoryWrapper/IRepositoryWrapper: 11 propiedades que ningun controller usa
- PickingRepository: TotalDetalle_Parcial y _Invoice sin uso; ReciboRepository: SerieOrigen sin uso

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-14 19:29:41 -05:00
11 changed files with 66 additions and 532 deletions

No files matched your search

+16 -13
View File
@@ -10,7 +10,7 @@ comprimido (versión antigua)**.
## Versión y control de versiones ## Versión y control de versiones
- **Versión actual: 2.1.7.0** (`Net.Business.Services.csproj`: `Version`, - **Versión actual: 2.1.8.0** (rama `limpieza-2.1.8.0`; `main` = 2.1.7.0) (`Net.Business.Services.csproj`: `Version`,
`AssemblyVersion`, `FileVersion`). Cada versión tiene su commit; al publicar `AssemblyVersion`, `FileVersion`). Cada versión tiene su commit; al publicar
se sube la versión (ver `publicar.ps1`). se sube la versión (ver `publicar.ps1`).
- **Git**: rama `main`, remoto `origin` = - **Git**: rama `main`, remoto `origin` =
@@ -86,6 +86,15 @@ transferencias siempre, sin depender de `Notificacion`. Detalle y tabla en
comparaba la serie origen (p. ej. `B005`) con `"03"` y siempre salía `FC10`. comparaba la serie origen (p. ej. `B005`) con `"03"` y siempre salía `FC10`.
Pendiente: validar con contabilidad la serie de boletas, y que Recibo no Pendiente: validar con contabilidad la serie de boletas, y que Recibo no
genera transferencias por almacén destino (nunca llena `U_ITC_ALMDES`). genera transferencias por almacén destino (nunca llena `U_ITC_ALMDES`).
- **v2.1.8.0 — limpieza y comentarios** (rama `limpieza-2.1.8.0`, sin cambios de
comportamiento): se quitó código sin uso (`ValidarCertificado`, `Logout`,
`CancelAsyncSBA`, `DeleteAsyncSBA`, el `throw` inalcanzable de `PatchAsyncSBA`,
`HelperDB`, 11 propiedades de `RepositoryWrapper` sin uso, variables
`TotalDetalle_Parcial`/`_Invoice`/`SerieOrigen` y un `if` vacío en
`CreateHojaRuta`) y se agregaron comentarios en Picking, Recibo,
`ConnectionServiceLayer`, `CreditNotesRepository`, `InvoiceRepository` y
`RepositoryWrapper`. Sigue pendiente: código comentado, `Login`/`LoginPost`
duplicados y `PatchAsyncSBA`.
- Sin probar contra SAP: confirmar con la factura 292410 que SAP devuelve - 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. `BaseType`/`BaseEntry` en las líneas y `BatchNumbers` en las de la Entrega.
@@ -139,11 +148,9 @@ Picking, columna `HORA` en `B_Log`. Lo que **no** se trajo: `Chatbots` y
- `BE_ResultadoTransaccion<T>.NombreEstacion`: setter con recursión infinita - `BE_ResultadoTransaccion<T>.NombreEstacion`: setter con recursión infinita
(bomba de tiempo; hoy nada lo asigna). (bomba de tiempo; hoy nada lo asigna).
- `ConnectionServiceLayer.PatchAsyncSBA<T>`: con un `204` real devuelve `null` - `ConnectionServiceLayer.PatchAsyncSBA<T>`: con un `204` real devuelve `null`
sin marcar éxito. `Login()`/`LoginPost()` duplicados; `throw` inalcanzable sin marcar éxito. `Login()`/`LoginPost()` duplicados.
tras `return` en varios `catch`. - El cliente HTTP `bypass-ssl-validation` acepta cualquier certificado TLS hacia
- `ValidarCertificado` acepta cualquier certificado TLS (siempre `true`). el Service Layer (se quitó el método `ValidarCertificado`, que no se usaba).
- `HelperDB.SET(string query)` ejecuta SQL arbitrario; hoy sin llamadores
(candidato a borrar).
- `appsettings.json` (fuera de git, en `.gitignore`) contiene credenciales - `appsettings.json` (fuera de git, en `.gitignore`) contiene credenciales
reales en texto plano (SAP Service Layer, **HANA `B1ADMIN`**, semilla JWT). reales en texto plano (SAP Service Layer, **HANA `B1ADMIN`**, semilla JWT).
Rotar la contraseña de `B1ADMIN` (estuvo en el código fuente) y evaluar un Rotar la contraseña de `B1ADMIN` (estuvo en el código fuente) y evaluar un
@@ -152,13 +159,9 @@ 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 `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í 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. que un fallo del log puede devolver 500 tras haber creado el documento en SAP.
- Código sin uso (limpieza prevista en 2.1.8.0): `CancelAsyncSBA`, - En Picking y Recibo, si la transferencia automática de stock falla, el `if`
`DeleteAsyncSBA`, `Logout`, `ValidarCertificado`, `HelperDB.SET`; 11 de error está vacío: el fallo se ignora (la NC ya está creada) y no se informa
propiedades de `RepositoryWrapper` que ningún controller usa al consumidor.
(`CreditNotes`, `InvoiceRepository`, `ReturnRequest`, `StockTransfer`, etc.);
`TotalDetalle_Parcial` y `var _Invoice` (bloque PICKING) en
`PickingRepository`; `SerieOrigen` en `ReciboRepository`; el `if` vacío tras
`StockTransfer` en Picking (un fallo de la transferencia se ignora).
## Despliegue ## Despliegue
@@ -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.7</Version> <Version>2.1.8</Version>
<AssemblyVersion>2.1.7.0</AssemblyVersion> <AssemblyVersion>2.1.8.0</AssemblyVersion>
<FileVersion>2.1.7.0</FileVersion> <FileVersion>2.1.8.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
@@ -48,11 +48,7 @@ namespace Net.Connection.ServiceLayer
_responseLoginServiceLayer = new ResponseLoginServiceLayer(); _responseLoginServiceLayer = new ResponseLoginServiceLayer();
} }
private bool ValidarCertificado(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors ssl) // Inicia sesion en el Service Layer (cookie B1SESSION). Usa SapServiceLayer:company/user/password de appsettings.json
{
return true;
}
public async Task<ResponseLoginServiceLayer> Login() public async Task<ResponseLoginServiceLayer> Login()
{ {
try try
@@ -140,6 +136,7 @@ namespace Net.Connection.ServiceLayer
return _responseLoginServiceLayer; return _responseLoginServiceLayer;
} }
} }
// Igual que Login(); duplicado historico (candidato a unificar)
public async Task<ResponseLoginServiceLayer> LoginPost() public async Task<ResponseLoginServiceLayer> LoginPost()
{ {
try try
@@ -228,93 +225,7 @@ namespace Net.Connection.ServiceLayer
return _responseLoginServiceLayer; return _responseLoginServiceLayer;
} }
} }
public async Task<ResponseLoginServiceLayer> Logout() // GET al Service Layer. dinamico = true: la respuesta es una sola entidad (ej. Invoices(123)); false: coleccion { value: [...] }
{
try
{
// CONSTRUIMOS LA URL DE LA ACCIÓN
var urlBuilder_ = new StringBuilder();
urlBuilder_.Append(_url != null ? _url.TrimEnd('/') : "")
.Append("/Logout");
var url_ = urlBuilder_.ToString();
// RECUPERAMOS EL HttpClient
var client_ = _httpClient.CreateClient("bypass-ssl-validation");
using (var request_ = new HttpRequestMessage())
{
///////////////////////////////////////
// CONSTRUIMOS LA PETICIÓN (REQUEST) //
///////////////////////////////////////
// DEFINIMOS EL Content CON EL OBJETO A ENVIAR SERIALIZADO.
//request_.Content = new StringContent("{\"CompanyDB\":\"" + _company + "\",\"Password\":\"" + _password + "\",\"UserName\":\"" + _user + "\"}");
//// DEFINIMOS EL ContentType, EN ESTE CASO ES "application/json"
//request_.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
request_.Headers.Add("cache-control", "no-cache");
// DEFINIMOS EL MÉTODO HTTP
request_.Method = new HttpMethod("POST");
// DEFINIMOS LA URI
request_.RequestUri = new Uri(url_, System.UriKind.RelativeOrAbsolute);
// DEFINIMOS EL Accept, EN ESTE CASO ES "application/json"
request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json"));
/////////////////////////////////////////
// CONSTRUIMOS LA RESPUESTA (RESPONSE) //
/////////////////////////////////////////
// Utilizamos ConfigureAwait(false) para evitar el DeadLock.
var response_ = await client_.SendAsync(request_).ConfigureAwait(false);
// OBTENEMOS EL Content DEL RESPONSE como un String
// Utilizamos ConfigureAwait(false) para evitar el DeadLock.
var responseText_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
// SI ES LA RESPUESTA ESPERADA !! ...
if (response_.StatusCode == System.Net.HttpStatusCode.NoContent) // 204
{
// DESERIALIZAMOS Content DEL RESPONSE
_responseLoginServiceLayer = JsonConvert.DeserializeObject<ResponseLoginServiceLayer>(responseText_);
_responseLoginServiceLayer.ServicioActivo = true;
_responseLoginServiceLayer.MensajeLogin = "Cierre de Sesión Correcta";
return _responseLoginServiceLayer;
}
//else
//// SI NO SE ESTÁ AUTORIZADO ...
//if (response_.StatusCode == System.Net.HttpStatusCode.Unauthorized) // 401
//{
// _responseLoginServiceLayer = JsonConvert.DeserializeObject<ResponseLoginServiceLayer>(responseText_);
// _responseLoginServiceLayer.ServicioActivo = false;
// _responseLoginServiceLayer.MensajeLogin = "401 Unauthorized. Las credenciales de acceso del usuario son incorrectas.";
// return _responseLoginServiceLayer;
//}
//else
//// CUALQUIER OTRA RESPUESTA ...
//if (response_.StatusCode != System.Net.HttpStatusCode.OK && // 200
// response_.StatusCode != System.Net.HttpStatusCode.NoContent) // 204
//{
// _responseLoginServiceLayer = JsonConvert.DeserializeObject<ResponseLoginServiceLayer>(responseText_);
// _responseLoginServiceLayer.ServicioActivo = false;
// _responseLoginServiceLayer.MensajeLogin = "401 Unauthorized. Las credenciales de acceso del usuario son incorrectas.";
// return _responseLoginServiceLayer;
//}
// RETORNAMOS EL OBJETO POR DEFECTO ESPERADO
return _responseLoginServiceLayer;
}
}
catch (Exception ex)
{
_responseLoginServiceLayer.ServicioActivo = false;
_responseLoginServiceLayer.MensajeLogin = ex.Message.ToString();
return _responseLoginServiceLayer;
}
}
public async Task<List<T>> GetAsync<T>(string Query, int maxpagesize,bool dinamico = false) public async Task<List<T>> GetAsync<T>(string Query, int maxpagesize,bool dinamico = false)
{ {
try try
@@ -396,6 +307,8 @@ namespace Net.Connection.ServiceLayer
// PASAMOS LA EXCEPCIÓN A LA APP. // PASAMOS LA EXCEPCIÓN A LA APP.
} }
} }
// POST con cuerpo JSON. Reintenta una vez si la sesion expiro (401). Si SAP rechaza, devuelve Exito = false y guarda
// el JSON enviado con ErrorLogger (tabla ITCA_LOG_INTEGRACION)
public async Task<T> PostAsync<T>(string Query, object obj) public async Task<T> PostAsync<T>(string Query, object obj)
{ {
@@ -526,6 +439,7 @@ namespace Net.Connection.ServiceLayer
// PASAMOS LA EXCEPCIÓN A LA APP. // PASAMOS LA EXCEPCIÓN A LA APP.
} }
} }
// POST sin cuerpo para reabrir un documento (ej. Invoices(n)/Reopen). SAP responde 204 sin contenido y se toma como exito
public async Task<T> PostReOpen<T>(string Query) public async Task<T> PostReOpen<T>(string Query)
{ {
@@ -658,6 +572,7 @@ namespace Net.Connection.ServiceLayer
// PASAMOS LA EXCEPCIÓN A LA APP. // PASAMOS LA EXCEPCIÓN A LA APP.
} }
} }
// POST sin cuerpo para cerrar un documento (.../Close)
public async Task<T> PostClose<T>(string Query) public async Task<T> PostClose<T>(string Query)
{ {
@@ -786,230 +701,7 @@ namespace Net.Connection.ServiceLayer
// PASAMOS LA EXCEPCIÓN A LA APP. // PASAMOS LA EXCEPCIÓN A LA APP.
} }
} }
public async Task<T> CancelAsyncSBA<T>(string Query) // PATCH con cuerpo JSON. OJO: con un 204 real devuelve null sin marcar exito (bug conocido); para PATCH sin respuesta usar PatchNoContentAsync
{
try
{
// CONSTRUIMOS LA URL DE LA ACCIÓN
var urlBuilder_ = new StringBuilder();
urlBuilder_.Append(_url != null ? _url.TrimEnd('/') : "")
.Append("/" + Query);
var url_ = urlBuilder_.ToString();
// RECUPERAMOS EL HttpClient
var client_ = _httpClient.CreateClient("bypass-ssl-validation");
int NumError = 0;
band:
using (var request_ = new HttpRequestMessage())
{
///////////////////////////////////////
// CONSTRUIMOS LA PETICIÓN (REQUEST) //
///////////////////////////////////////
// DEFINIMOS EL MÉTODO HTTP GET
request_.Method = new HttpMethod("POST");
// DEFINIMOS LA URI
request_.RequestUri = new Uri(url_, System.UriKind.RelativeOrAbsolute);
// DEFINIMOS EL Accept, EN ESTE CASO ES "application/json"
//request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json"));
//request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("odata=minimalmetadata"));
//request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("charset=utf-8"));
//request_.Content = new StringContent(JsonConvert.SerializeObject(obj), System.Text.Encoding.UTF8, "application/json");
// ASIGNAMOS A LA CABECERA DE LA PETICIÓN EL TOKEN JWT.
if (_responseLoginServiceLayer.ServicioActivo)
request_.Headers.Add("Cookie", "B1SESSION=" + _responseLoginServiceLayer.SessionId);
/////////////////////////////////////////
// CONSTRUIMOS LA RESPUESTA (RESPONSE) //
/////////////////////////////////////////
// Utilizamos ConfigureAwait(false) para evitar el DeadLock.
var response_ = await client_.SendAsync(request_, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
// OBTENEMOS EL Content DEL RESPONSE como un String
// Utilizamos ConfigureAwait(false) para evitar el DeadLock.
var responseText_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
// SI ES LA RESPUESTA ESPERADA !! ...
if (response_.StatusCode == System.Net.HttpStatusCode.OK || response_.StatusCode == System.Net.HttpStatusCode.Created) // 200 or Created
{
// DESERIALIZAMOS Content DEL RESPONSE
dynamic responseBody = JsonConvert.DeserializeObject<T>(responseText_);
var estado = (int)response_.StatusCode;
//responseBody.CodigoHttp = estado.ToString();
responseBody.Mensaje = "SE ENVIO CORRECTAMENTE A SAP BO ";
return responseBody;
}
else
// SI NO SE ESTÁ AUTORIZADO ...
if (response_.StatusCode == System.Net.HttpStatusCode.Unauthorized) // 401
{
NumError += 1;
_responseLoginServiceLayer = JsonConvert.DeserializeObject<ResponseLoginServiceLayer>(responseText_);
_responseLoginServiceLayer.ServicioActivo = false;
if (NumError == 2)
{
dynamic responseBody = JsonConvert.DeserializeObject<T>(responseText_);
var estado = (int)response_.StatusCode;
//responseBody.CodigoHttp = estado.ToString();
responseBody.Mensaje = "Services Unauthorized : " + _responseLoginServiceLayer.error.message.ToString();
return responseBody;
}
if (_responseLoginServiceLayer.error.code.ToString() == "301")
{
await LoginPost();
goto band;
}
}
else
// CUALQUIER OTRA RESPUESTA ...
if (response_.StatusCode != System.Net.HttpStatusCode.OK && // 200
response_.StatusCode != System.Net.HttpStatusCode.NoContent) // 204
{
//NumError += 1;
_responseLoginServiceLayer = JsonConvert.DeserializeObject<ResponseLoginServiceLayer>(responseText_);
_responseLoginServiceLayer.ServicioActivo = false;
dynamic responseBody = JsonConvert.DeserializeObject<T>(responseText_);
var estado = (int)response_.StatusCode;
//responseBody.CodigoHttp = estado.ToString();
responseBody.Mensaje = "Error Services : " + _responseLoginServiceLayer.error.message.ToString();
return responseBody;
}
// RETORNAMOS EL OBJETO POR DEFECTO ESPERADO
return default(T);
}
}
catch (Exception ex)
{
return default(T);
throw new Exception(ex.Message.ToString());
}
}
public async Task<T> DeleteAsyncSBA<T>(string Query)
{
try
{
// CONSTRUIMOS LA URL DE LA ACCIÓN
var urlBuilder_ = new StringBuilder();
urlBuilder_.Append(_url != null ? _url.TrimEnd('/') : "")
.Append("/" + Query);
var url_ = urlBuilder_.ToString();
// RECUPERAMOS EL HttpClient
var client_ = _httpClient.CreateClient("bypass-ssl-validation");
int NumError = 0;
band:
using (var request_ = new HttpRequestMessage())
{
///////////////////////////////////////
// CONSTRUIMOS LA PETICIÓN (REQUEST) //
///////////////////////////////////////
// DEFINIMOS EL MÉTODO HTTP GET
request_.Method = new HttpMethod("DELETE");
// DEFINIMOS LA URI
request_.RequestUri = new Uri(url_, System.UriKind.RelativeOrAbsolute);
// DEFINIMOS EL Accept, EN ESTE CASO ES "application/json"
//request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json"));
//request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("odata=minimalmetadata"));
//request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("charset=utf-8"));
//request_.Content = new StringContent(JsonConvert.SerializeObject(obj), System.Text.Encoding.UTF8, "application/json");
// ASIGNAMOS A LA CABECERA DE LA PETICIÓN EL TOKEN JWT.
if (_responseLoginServiceLayer.ServicioActivo)
request_.Headers.Add("Cookie", "B1SESSION=" + _responseLoginServiceLayer.SessionId);
/////////////////////////////////////////
// CONSTRUIMOS LA RESPUESTA (RESPONSE) //
/////////////////////////////////////////
// Utilizamos ConfigureAwait(false) para evitar el DeadLock.
var response_ = await client_.SendAsync(request_, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
// OBTENEMOS EL Content DEL RESPONSE como un String
// Utilizamos ConfigureAwait(false) para evitar el DeadLock.
var responseText_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
// SI ES LA RESPUESTA ESPERADA !! ...
if (response_.StatusCode == System.Net.HttpStatusCode.OK || response_.StatusCode == System.Net.HttpStatusCode.Created) // 200 or Created
{
// DESERIALIZAMOS Content DEL RESPONSE
dynamic responseBody = JsonConvert.DeserializeObject<T>(responseText_);
var estado = (int)response_.StatusCode;
//responseBody.CodigoHttp = estado.ToString();
responseBody.Mensaje = "SE ENVIO CORRECTAMENTE A SAP BO ";
return responseBody;
}
else
// SI NO SE ESTÁ AUTORIZADO ...
if (response_.StatusCode == System.Net.HttpStatusCode.Unauthorized) // 401
{
NumError += 1;
_responseLoginServiceLayer = JsonConvert.DeserializeObject<ResponseLoginServiceLayer>(responseText_);
_responseLoginServiceLayer.ServicioActivo = false;
if (NumError == 2)
{
dynamic responseBody = JsonConvert.DeserializeObject<T>(responseText_);
var estado = (int)response_.StatusCode;
//responseBody.CodigoHttp = estado.ToString();
responseBody.Mensaje = "Services Unauthorized : " + _responseLoginServiceLayer.error.message.ToString();
return responseBody;
}
if (_responseLoginServiceLayer.error.code.ToString() == "301")
{
await LoginPost();
goto band;
}
}
else
// CUALQUIER OTRA RESPUESTA ...
if (response_.StatusCode != System.Net.HttpStatusCode.OK && // 200
response_.StatusCode != System.Net.HttpStatusCode.NoContent) // 204
{
//NumError += 1;
_responseLoginServiceLayer = JsonConvert.DeserializeObject<ResponseLoginServiceLayer>(responseText_);
_responseLoginServiceLayer.ServicioActivo = false;
dynamic responseBody = JsonConvert.DeserializeObject<T>(responseText_);
var estado = (int)response_.StatusCode;
//responseBody.CodigoHttp = estado.ToString();
responseBody.Mensaje = "Error Services : " + _responseLoginServiceLayer.error.message.ToString();
return responseBody;
}
// RETORNAMOS EL OBJETO POR DEFECTO ESPERADO
return default(T);
}
}
catch (Exception ex)
{
return default(T);
throw new Exception(ex.Message.ToString());
}
}
public async Task<T> PatchAsyncSBA<T>(string Query, object obj) public async Task<T> PatchAsyncSBA<T>(string Query, object obj)
{ {
try try
@@ -1127,7 +819,6 @@ namespace Net.Connection.ServiceLayer
catch (Exception ex) catch (Exception ex)
{ {
return default(T); return default(T);
throw new Exception(ex.Message.ToString());
} }
} }
@@ -28,20 +28,9 @@ namespace Net.Data
#endregion #endregion
#region SAP (SERVICES LAYER) #region SAP (SERVICES LAYER)
IBusinessPartnersRepository BusinessPartners { get; }
ICreditNotesRepository CreditNotes { get; }
IPurchaseInvoicesRepository PurchaseInvoices { get; }
IInvoiceRepository InvoiceRepository { get; }
IPurchaseDeliveryNotesRepository PurchaseDeliveryNotes { get; }
IPurchaseOrdersRepository PurchaseOrders { get; }
IAuthenticateRepository Authenticate { get; } IAuthenticateRepository Authenticate { get; }
IItemsRepository Items { get; } IItemsRepository Items { get; }
IReturnRequestRepository ReturnRequest { get; }
IStockTransferRepository StockTransfer { get; }
IInventoryGenEntriesRepository InventoryGenEntries { get; }
IInventoryGenExitsRepository InventoryGenExits { get; }
IHRRepository HR { get; } IHRRepository HR { get; }
IGlobalDataRepository GlobalData { get; }
#endregion #endregion
@@ -21,6 +21,8 @@ using System.Net.Http;
namespace Net.Data namespace Net.Data
{ {
// Expone solo los repositorios que usan los controllers. Los de Service Layer (CreditNotes, Invoice, StockTransfer, ReturnRequest...)
// se instancian directamente con new donde se necesitan.
public class RepositoryWrapper : IRepositoryWrapper public class RepositoryWrapper : IRepositoryWrapper
{ {
#region Variables de conexion #region Variables de conexion
@@ -42,7 +44,6 @@ namespace Net.Data
private IReciboRepository _Recibo; private IReciboRepository _Recibo;
private ITransferenciaRepository _Transferencia; private ITransferenciaRepository _Transferencia;
private IStockTransferRepository _StockTransfer;
private IPickingRepository _Picking; private IPickingRepository _Picking;
private IInventarioRepository _Inventario; private IInventarioRepository _Inventario;
private ISolicitudTransferenciaRepository _SolicitudTransferencia; private ISolicitudTransferenciaRepository _SolicitudTransferencia;
@@ -51,19 +52,9 @@ namespace Net.Data
#region SAP (SERVICES LAYER) #region SAP (SERVICES LAYER)
private IBusinessPartnersRepository _BusinessPartners;
private IPurchaseInvoicesRepository _PurchaseInvoices;
private IInvoiceRepository _Invoice;
private ICreditNotesRepository _CreditNotes;
private IAuthenticateRepository _AuthenticateRepository; private IAuthenticateRepository _AuthenticateRepository;
private IPurchaseDeliveryNotesRepository _PurchaseDeliveryNotes;
private IPurchaseOrdersRepository _PurchaseOrders;
private IItemsRepository _Items; private IItemsRepository _Items;
private IReturnRequestRepository _ReturnRequest;
private IInventoryGenEntriesRepository _InventoryGenEntries;
private IInventoryGenExitsRepository _InventoryGenExits;
private IHRRepository _HR; private IHRRepository _HR;
private IGlobalDataRepository _GlobalData;
#endregion #endregion
@@ -162,79 +153,6 @@ namespace Net.Data
#endregion #endregion
#region SAP (SERVICES LAYER) #region SAP (SERVICES LAYER)
public IBusinessPartnersRepository BusinessPartners
{
get
{
if (_BusinessPartners == null)
{
_repoContext._cnx = _conSQL;
_BusinessPartners = new BusinessPartnersRepository(_clientFactory, _configuration, _repoContext);
}
return _BusinessPartners;
}
}
public ICreditNotesRepository CreditNotes
{
get
{
if (_CreditNotes == null)
{
_repoContext._cnx = _conSQL;
_CreditNotes = new CreditNotesRepository(_clientFactory, _configuration, _repoContext);
}
return _CreditNotes;
}
}
public IInvoiceRepository InvoiceRepository
{
get
{
if (_Invoice == null)
{
_repoContext._cnx = _conSQL;
_Invoice = new InvoiceRepository(_clientFactory, _configuration, _repoContext);
}
return _Invoice;
}
}
public IPurchaseInvoicesRepository PurchaseInvoices
{
get
{
if (_PurchaseInvoices == null)
{
_repoContext._cnx = _conSQL;
_PurchaseInvoices = new PurchaseInvoicesRepository(_clientFactory, _configuration);
}
return _PurchaseInvoices;
}
}
public IPurchaseDeliveryNotesRepository PurchaseDeliveryNotes
{
get
{
if (_PurchaseDeliveryNotes == null)
{
_repoContext._cnx = _conSQL;
_PurchaseDeliveryNotes = new PurchaseDeliveryNotesRepository(_clientFactory, _configuration);
}
return _PurchaseDeliveryNotes;
}
}
public IPurchaseOrdersRepository PurchaseOrders
{
get
{
if (_PurchaseOrders == null)
{
_repoContext._cnx = _conSQL;
_PurchaseOrders = new PurchaseOrdersRepository(_clientFactory, _configuration);
}
return _PurchaseOrders;
}
}
public IAuthenticateRepository Authenticate public IAuthenticateRepository Authenticate
{ {
get get
@@ -247,54 +165,6 @@ namespace Net.Data
return _AuthenticateRepository; return _AuthenticateRepository;
} }
} }
public IReturnRequestRepository ReturnRequest
{
get
{
if(_ReturnRequest == null)
{
_repoContext._cnx = _conSQL;
_ReturnRequest = new ReturnRequestRepository(_clientFactory, _configuration);
}
return _ReturnRequest;
}
}
public IStockTransferRepository StockTransfer
{
get
{
if (_StockTransfer == null)
{
_repoContext._cnx = _conSQL;
_StockTransfer = new StockTransferRepository(_clientFactory, _configuration);
}
return _StockTransfer;
}
}
public IInventoryGenEntriesRepository InventoryGenEntries
{
get
{
if (_InventoryGenEntries == null)
{
_repoContext._cnx = _conSQL;
_InventoryGenEntries = new InventoryGenEntriesRepository(_clientFactory, _configuration, _repoContext);
}
return _InventoryGenEntries;
}
}
public IInventoryGenExitsRepository InventoryGenExits
{
get
{
if (_InventoryGenExits == null)
{
_repoContext._cnx = _conSQL;
_InventoryGenExits = new InventoryGenExitsRepository(_clientFactory, _configuration, _repoContext);
}
return _InventoryGenExits;
}
}
public IHRRepository HR public IHRRepository HR
{ {
@@ -309,18 +179,6 @@ namespace Net.Data
} }
} }
public IGlobalDataRepository GlobalData
{
get
{
if (_GlobalData == null)
{
_repoContext._cnx = _conSQL;
_GlobalData = new GlobalDataRepository(_clientFactory, _configuration, _repoContext);
}
return _GlobalData;
}
}
#endregion #endregion
} }
} }
-27
View File
@@ -1,27 +0,0 @@
using Sap.Data.Hana;
using System.Data;
namespace Net.Data.HelperData
{
public class HelperDB
{
public static void SET(string query)
{
using (HanaConnection con = new HanaConnection(LocalData.ConnectionString))
{
con.Open();
HanaCommand cmd = new HanaCommand
{
CommandText = query,
Connection = con,
CommandType = CommandType.Text
};
cmd.ExecuteNonQuery();
con.Close();
}
}
}
}
@@ -36,6 +36,8 @@ namespace Net.Data.ServicesLayer.CreditNotes
_context = context; _context = context;
} }
// Crea la nota de credito en SAP (POST CreditNotes). Si SAP rechaza, devuelve StatusCode -1 con el mensaje de SAP;
// el JSON enviado queda en el log (ver ConnectionServiceLayer.PostAsync)
public async Task<BE_ResultadoTransaccion<BE_BaseResponseSap>> SetCreateCreditNotes(BE_CreditNotesNotes entidad) public async Task<BE_ResultadoTransaccion<BE_BaseResponseSap>> SetCreateCreditNotes(BE_CreditNotesNotes entidad)
{ {
_metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString();
@@ -62,6 +64,7 @@ namespace Net.Data.ServicesLayer.CreditNotes
} }
// Actualiza una NC ya creada (PATCH); se usa para agregar las referencias de las transferencias automaticas
public async Task<BE_ResultadoTransaccion<BE_BaseResponseSap>> UpdateCreateCreditNotes(dynamic entidad, int DocEntry) public async Task<BE_ResultadoTransaccion<BE_BaseResponseSap>> UpdateCreateCreditNotes(dynamic entidad, int DocEntry)
{ {
_metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString();
@@ -72,6 +72,7 @@ namespace Net.Data.ServicesLayer
} }
// GET INVOICES // GET INVOICES
// Lee una factura de venta (GET Invoices(docEntry)): cabecera, campos U_SYP_*, lineas con BaseType/BaseEntry/BaseLine y lotes
public async Task<BE_ResultadoTransaccion<BE_InvoicesConsulta>> GetInvoice(int docEntry) public async Task<BE_ResultadoTransaccion<BE_InvoicesConsulta>> GetInvoice(int docEntry)
{ {
_metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString();
@@ -111,6 +112,7 @@ namespace Net.Data.ServicesLayer
} }
} }
// Reabre una factura cerrada (POST Invoices(n)/Reopen); la NC solo se puede crear sobre una factura abierta
public async Task<BE_ResultadoTransaccion<BE_BaseResponseSap>> ReOpen(int docEntry) public async Task<BE_ResultadoTransaccion<BE_BaseResponseSap>> ReOpen(int docEntry)
{ {
_metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString();
+20 -9
View File
@@ -52,6 +52,10 @@ namespace Net.Data.WMS.Picking
_aplicacionName = GetType().Name; _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) public async Task<BE_ResultadoTransaccion<object>> Create(BE_PickingRequest entidad)
{ {
_metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString();
@@ -67,6 +71,7 @@ namespace Net.Data.WMS.Picking
{ {
try 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); var Almacen = HelperProcesoPermitido.GetMotivoAlmacen(entidad.CodMotivo, out bool Reproceso, out string MotivoNotaCredito, out string DescripcionMotivo);
if (string.IsNullOrEmpty(entidad.Proceso)) if (string.IsNullOrEmpty(entidad.Proceso))
@@ -88,13 +93,11 @@ namespace Net.Data.WMS.Picking
var TotalDetalle = 0; var TotalDetalle = 0;
var TotalDetalle_Anulado = 0; var TotalDetalle_Anulado = 0;
var TotalDetalle_Parcial = 0;
var TotalDetalle_Completo = 0; var TotalDetalle_Completo = 0;
if (Existe > 1) if (Existe > 1)
{ {
TotalDetalle = entidad.Detalle.Count(); TotalDetalle = entidad.Detalle.Count();
TotalDetalle_Anulado = entidad.Detalle.Where(x=> x.Estado == "A").Count(); TotalDetalle_Anulado = entidad.Detalle.Where(x=> x.Estado == "A").Count();
TotalDetalle_Parcial = entidad.Detalle.Where(x => x.Estado == "P").Count();
TotalDetalle_Completo = entidad.Detalle.Where(x => x.Estado == "C").Count(); TotalDetalle_Completo = entidad.Detalle.Where(x => x.Estado == "C").Count();
if(TotalDetalle == TotalDetalle_Anulado) if(TotalDetalle == TotalDetalle_Anulado)
{ {
@@ -113,7 +116,6 @@ namespace Net.Data.WMS.Picking
{ {
TotalDetalle = entidad.Detalle.Count(); TotalDetalle = entidad.Detalle.Count();
TotalDetalle_Anulado = entidad.Detalle.Where(x => x.Estado == "A").Count(); TotalDetalle_Anulado = entidad.Detalle.Where(x => x.Estado == "A").Count();
TotalDetalle_Parcial = entidad.Detalle.Where(x => x.Estado == "P").Count();
TotalDetalle_Completo = entidad.Detalle.Where(x => x.Estado == "C").Count(); TotalDetalle_Completo = entidad.Detalle.Where(x => x.Estado == "C").Count();
} }
@@ -129,6 +131,7 @@ namespace Net.Data.WMS.Picking
{ {
return resultadoTransaccion.GetInformacionResultado(entidad.DocEntry, entidad.NumOrden, "Estado actualizado correctamente", entidad); 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) if(TotalDetalle == TotalDetalle_Completo && entidad.IdTipoDoc != 9)
{ {
return resultadoTransaccion.GetInformacionResultado(entidad.DocEntry, entidad.NumOrden, "Se registro correctamente...!!!", entidad); return resultadoTransaccion.GetInformacionResultado(entidad.DocEntry, entidad.NumOrden, "Se registro correctamente...!!!", entidad);
@@ -136,6 +139,7 @@ namespace Net.Data.WMS.Picking
#region PROCESO DE NOTA DE CREDITO #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.Proceso.ToUpper() == "DESPACHO" && (entidad.IdEstadoCubico == 6 || entidad.IdEstadoCubico == 5))
{ {
if (entidad.IdTipoDoc != 9) if (entidad.IdTipoDoc != 9)
@@ -167,6 +171,8 @@ namespace Net.Data.WMS.Picking
} }
} }
// 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 Serie = _invoices.U_SYP_MDTD == "03" ? "BC10" : "FC10";
string Correlativo = HelperCorrelativo.Get(Serie); string Correlativo = HelperCorrelativo.Get(Serie);
creditNotesNotes.DocCurrency = _invoices.DocCurrency; creditNotesNotes.DocCurrency = _invoices.DocCurrency;
@@ -293,6 +299,7 @@ namespace Net.Data.WMS.Picking
} }
else 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<string> ListaUnicaAlmacen = creditNotesNotes.DocumentLines.Select(x => x.WarehouseCode).Distinct().ToList();
List<int> ListDocEntry = new List<int>(); List<int> ListDocEntry = new List<int>();
ListaUnicaAlmacen.ForEach(Almacen => ListaUnicaAlmacen.ForEach(Almacen =>
@@ -358,6 +365,7 @@ namespace Net.Data.WMS.Picking
//=== CREA INSTANCIA PARA CONECTAR A SAP //=== CREA INSTANCIA PARA CONECTAR A SAP
StockTransferRepository stockTransferRepository = new StockTransferRepository(_clientFactory, _configuration); StockTransferRepository stockTransferRepository = new StockTransferRepository(_clientFactory, _configuration);
var ResultTransfer = stockTransferRepository.StockTransfer(Transfer).Result; 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) if (ResultTransfer.StatusCode == -1)
{ {
@@ -371,6 +379,7 @@ namespace Net.Data.WMS.Picking
}); });
// Referencia las transferencias creadas en la NC
if (ListDocEntry.Count > 0) if (ListDocEntry.Count > 0)
{ {
var listaReferencia = new List<BE_CreditNotesDocumentReferences>(); var listaReferencia = new List<BE_CreditNotesDocumentReferences>();
@@ -500,6 +509,7 @@ namespace Net.Data.WMS.Picking
} }
} }
// 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) if (entidad.Proceso.ToUpper() == "PICKING" && entidad.IdEstadoCubico == 13)
{ {
CreditNotesRepository _creditNotesRepository = new CreditNotesRepository(_clientFactory, _configuration, context); CreditNotesRepository _creditNotesRepository = new CreditNotesRepository(_clientFactory, _configuration, context);
@@ -527,6 +537,7 @@ namespace Net.Data.WMS.Picking
} }
} }
// Serie segun el tipo de documento de la factura (03 = boleta -> BC10, otro -> FC10)
string Serie = _invoices.U_SYP_MDTD == "03" ? "BC10" : "FC10"; string Serie = _invoices.U_SYP_MDTD == "03" ? "BC10" : "FC10";
string Correlativo = HelperCorrelativo.Get(Serie); string Correlativo = HelperCorrelativo.Get(Serie);
@@ -571,7 +582,6 @@ namespace Net.Data.WMS.Picking
} }
}); });
var _Invoice = response_invoicesRepository.ListData.FirstOrDefault();
creditNotesNotes.DocumentLines.ForEach(line => creditNotesNotes.DocumentLines.ForEach(line =>
{ {
@@ -588,6 +598,7 @@ namespace Net.Data.WMS.Picking
else else
{ {
// Transferencias automaticas por almacen origen/destino (igual que en DESPACHO)
List<string> ListaUnicaAlmacen = creditNotesNotes.DocumentLines.Select(x => x.WarehouseCode).Distinct().ToList(); List<string> ListaUnicaAlmacen = creditNotesNotes.DocumentLines.Select(x => x.WarehouseCode).Distinct().ToList();
List<int> ListDocEntry = new List<int>(); List<int> ListDocEntry = new List<int>();
ListaUnicaAlmacen.ForEach(Almacen => ListaUnicaAlmacen.ForEach(Almacen =>
@@ -650,6 +661,7 @@ namespace Net.Data.WMS.Picking
//=== CREA INSTANCIA PARA CONECTAR A SAP //=== CREA INSTANCIA PARA CONECTAR A SAP
StockTransferRepository stockTransferRepository = new StockTransferRepository(_clientFactory, _configuration); StockTransferRepository stockTransferRepository = new StockTransferRepository(_clientFactory, _configuration);
var ResultTransfer = stockTransferRepository.StockTransfer(Transfer).Result; var ResultTransfer = stockTransferRepository.StockTransfer(Transfer).Result;
// OJO: si la transferencia falla se ignora (la NC ya esta creada)
if (ResultTransfer.StatusCode == -1) if (ResultTransfer.StatusCode == -1)
{ {
@@ -690,6 +702,8 @@ namespace Net.Data.WMS.Picking
return resultadoTransaccion.GetInformacionResultado((int)entidad.DocEntry, entidad.NumOrden.ToString(), "Se registro correctamente...!!!", entidad); 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(entidad.Proceso.ToUpper() == "ULTIMA MILLA" && entidad.IdEstadoCubico == 23)
{ {
if(Proceso.U_ITCA_GNRPROC == "SOLICITUD DEV" && !Reproceso) if(Proceso.U_ITCA_GNRPROC == "SOLICITUD DEV" && !Reproceso)
@@ -769,6 +783,7 @@ namespace Net.Data.WMS.Picking
}); });
} }
// 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) public async Task<BE_ResultadoTransaccion<object>> CreateHojaRuta(BE_HojaRutaEntities entidad)
{ {
_metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString(); _metodoName = regex.Match(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name).Groups[1].Value.ToString();
@@ -801,11 +816,6 @@ namespace Net.Data.WMS.Picking
} }
HelperProcesoPiciking.Set(entidad.Proceso, entidad.IdEstadoCubico, entidad.DocEntry, HelperProcesoPermitido.ConvertTimeToInteger(entidad.HoraInicio), HelperProcesoPermitido.ConvertTimeToInteger(entidad.FinRuta), entidad.CodMotivo, ListaProceso.FirstOrDefault().Code); HelperProcesoPiciking.Set(entidad.Proceso, entidad.IdEstadoCubico, entidad.DocEntry, HelperProcesoPermitido.ConvertTimeToInteger(entidad.HoraInicio), HelperProcesoPermitido.ConvertTimeToInteger(entidad.FinRuta), entidad.CodMotivo, ListaProceso.FirstOrDefault().Code);
if (entidad.Proceso == "Picking")
{
//=== IDENTIFICA DESCRIPCION DE ESTADO
}
return resultadoTransaccion.GetInformacionResultado(entidad.DocEntry, entidad.DocEntry.ToString(), "Registrado Correctamente", entidad); return resultadoTransaccion.GetInformacionResultado(entidad.DocEntry, entidad.DocEntry.ToString(), "Registrado Correctamente", entidad);
} }
catch (Exception ex) catch (Exception ex)
@@ -815,6 +825,7 @@ namespace Net.Data.WMS.Picking
}); });
} }
// 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) public async Task<BE_ResultadoTransaccion<object>> CerrarHojaRuta(int docEntry)
{ {
_metodoName = "CerrarHojaRuta"; _metodoName = "CerrarHojaRuta";
+7 -3
View File
@@ -345,6 +345,8 @@ namespace Net.Data.WMS.Recibo
#endregion #endregion
// DEVOLUCION: NC (oCreditNotes) con base en la Solicitud de Devolucion (BaseType 234000031).
// Si las lineas de la solicitud vienen de una factura se usan los datos y lotes de la factura; si no, los de la solicitud y el stock de HANA
#region PROCESO DE NOTA DE CREDITO #region PROCESO DE NOTA DE CREDITO
if (entidad.IdTipo == EnumRecibo.DEVOLUCION) if (entidad.IdTipo == EnumRecibo.DEVOLUCION)
@@ -379,7 +381,6 @@ namespace Net.Data.WMS.Recibo
_Invoice = _Invoice_Result.ListData.FirstOrDefault(); _Invoice = _Invoice_Result.ListData.FirstOrDefault();
} }
}); });
string SerieOrigen = "";
string U_SYP_MDTO = ""; string U_SYP_MDTO = "";
string U_SYP_MDCO = ""; string U_SYP_MDCO = "";
string U_SYP_MDSO = ""; string U_SYP_MDSO = "";
@@ -387,7 +388,6 @@ namespace Net.Data.WMS.Recibo
if (_Invoice == null) if (_Invoice == null)
{ {
SerieOrigen = returnRequest.U_SYP_MDSO;
U_SYP_MDTO = returnRequest.U_SYP_MDTO; U_SYP_MDTO = returnRequest.U_SYP_MDTO;
U_SYP_MDCO = returnRequest.U_SYP_MDCO; U_SYP_MDCO = returnRequest.U_SYP_MDCO;
U_SYP_MDSO = returnRequest.U_SYP_MDSO; U_SYP_MDSO = returnRequest.U_SYP_MDSO;
@@ -395,7 +395,6 @@ namespace Net.Data.WMS.Recibo
} }
else else
{ {
SerieOrigen = _Invoice.U_SYP_MDSD;
U_SYP_MDTO = _Invoice.U_SYP_MDTD; U_SYP_MDTO = _Invoice.U_SYP_MDTD;
U_SYP_MDCO = _Invoice.U_SYP_MDCD; U_SYP_MDCO = _Invoice.U_SYP_MDCD;
U_SYP_MDSO = _Invoice.U_SYP_MDSD; U_SYP_MDSO = _Invoice.U_SYP_MDSD;
@@ -404,6 +403,7 @@ namespace Net.Data.WMS.Recibo
#endregion #endregion
// Serie segun el TIPO de documento origen (03 = boleta), no segun su serie // Serie segun el TIPO de documento origen (03 = boleta), no segun su serie
// El correlativo sale de @SYP_NUMDOC (HelperCorrelativo)
string Serie = U_SYP_MDTO == "03" ? "BC10" : "FC10"; string Serie = U_SYP_MDTO == "03" ? "BC10" : "FC10";
string Correlativo = HelperCorrelativo.Get(Serie); string Correlativo = HelperCorrelativo.Get(Serie);
creditNotesNotes.DocCurrency = returnRequest.DocCurrency; creditNotesNotes.DocCurrency = returnRequest.DocCurrency;
@@ -452,6 +452,8 @@ namespace Net.Data.WMS.Recibo
} }
}); });
// Lotes de cada linea: sin factura relacionada, FIFO por vencimiento del stock de HANA; con factura, los lotes de la factura.
// En ambos casos se parte de la lista vacia para que los lotes sumen exactamente la cantidad de la linea
if (_Invoice == null) if (_Invoice == null)
{ {
//=== REALIZA DISTRIBUCION DE STOCK POR LOTE //=== REALIZA DISTRIBUCION DE STOCK POR LOTE
@@ -535,6 +537,7 @@ namespace Net.Data.WMS.Recibo
} }
else 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<string> ListaUnicaAlmacen = creditNotesNotes.DocumentLines.Select(x => x.WarehouseCode).Distinct().ToList();
List<int> ListDocEntry = new List<int>(); List<int> ListDocEntry = new List<int>();
ListaUnicaAlmacen.ForEach(Almacen => ListaUnicaAlmacen.ForEach(Almacen =>
@@ -597,6 +600,7 @@ namespace Net.Data.WMS.Recibo
//=== CREA INSTANCIA PARA CONECTAR A SAP //=== CREA INSTANCIA PARA CONECTAR A SAP
StockTransferRepository stockTransferRepository = new StockTransferRepository(_clientFactory, _configuration); StockTransferRepository stockTransferRepository = new StockTransferRepository(_clientFactory, _configuration);
var ResultTransfer = stockTransferRepository.StockTransfer(Transfer).Result; var ResultTransfer = stockTransferRepository.StockTransfer(Transfer).Result;
// OJO: si la transferencia falla se ignora (la NC ya esta creada)
if (ResultTransfer.StatusCode == -1) if (ResultTransfer.StatusCode == -1)
{ {
+5 -5
View File
@@ -76,7 +76,7 @@ dotnet publish Net.Business.Services/Net.Business.Services.csproj -c Release -r
## Versión y script de publish ## Versión y script de publish
- La versión sale de `<Version>`/`<AssemblyVersion>`/`<FileVersion>` en - La versión sale de `<Version>`/`<AssemblyVersion>`/`<FileVersion>` en
`Net.Business.Services/Net.Business.Services.csproj` (actual: **2.1.7.0**); `Net.Business.Services/Net.Business.Services.csproj` (actual: **2.1.8.0** en la rama de limpieza; `main` = 2.1.7.0);
súbela en cada publish. súbela en cada publish.
- `publicar.ps1` (solo Windows) genera `dist\ITCA_API_SAP_WMS_v<versión>.zip` sin - `publicar.ps1` (solo Windows) genera `dist\ITCA_API_SAP_WMS_v<versión>.zip` sin
`appsettings.json`. Desde macOS se hace el mismo `dotnet publish` a mano con `appsettings.json`. Desde macOS se hace el mismo `dotnet publish` a mano con
@@ -198,7 +198,7 @@ para armar el body del `Login` contra el Service Layer.
ejecutar los `ITCA_*` y leer algunas tablas. Conviene un usuario HANA de ejecutar los `ITCA_*` y leer algunas tablas. Conviene un usuario HANA de
permisos mínimos y rotar la contraseña (estuvo en texto plano en el código permisos mínimos y rotar la contraseña (estuvo en texto plano en el código
y en el historial git del repo antiguo archivado). y en el historial git del repo antiguo archivado).
- `ValidarCertificado` en `ConnectionServiceLayer.cs` acepta cualquier - El cliente HTTP `bypass-ssl-validation` (usado por `ConnectionServiceLayer`)
certificado TLS (`return true;` siempre) — bypass de validación de acepta cualquier certificado TLS — bypass de validación de certificado hacia
certificado hacia el Service Layer, igual criterio que el Service Layer, igual criterio que `SERVICE_LAYER_VERIFY_SSL=false` en la
`SERVICE_LAYER_VERIFY_SSL=false` en la reescritura Python. reescritura Python. (Se quitó el método `ValidarCertificado`, que no se usaba.)