Leandro Hernan Rojas 852eab0c32
All checks were successful
CI/CD Pipeline / Build and Deploy with Docker Compose (push) Successful in 6m39s
Add StockScanController
2025-08-18 09:28:05 -03:00

125 lines
5.1 KiB
C#

using System.Net.Http.Json;
using Domain.Dtos.Stock;
using Domain.Generics;
//using Transversal.Services;
public class StockScanService : IStockScanService
{
private readonly HttpClient _http;
public StockScanService(HttpClient http)
{
_http = http;
}
public async Task<StockItemSelectionDto?> ParseAndMatchAsync(string rawInput, int locationId)
{
if (string.IsNullOrWhiteSpace(rawInput)) return null;
var payload = new { Raw = rawInput, LocationId = locationId, Page = 1, PageSize = 10 };
var resp = await _http.PostAsJsonAsync("/api/lsstockscan/parse-and-search", payload);
if (!resp.IsSuccessStatusCode) return null;
var pr = await resp.Content.ReadFromJsonAsync<PagedResult<StockItemScanResultDto>>();
var first = pr?.Items?.FirstOrDefault();
if (first is null) return null;
return new StockItemSelectionDto
{
StockItemId = first.StockItemId,
ProductId = first.ProductId,
ProductName = first.ProductName,
Batch = first.Batch ?? string.Empty,
Expiration = first.Expiration?.ToDateTime(TimeOnly.MinValue),
Quantity = first.AvailableQty,
LocationId = first.LocationId ?? locationId,
Serial = first.Serial // si lo devolvés en el DTO de scan
};
}
//public async Task<StockItemSelectionDto?> ParseAndMatchAsync(string rawInput, int locationId)
//{
// if (string.IsNullOrWhiteSpace(rawInput))
// return null;
// try
// {
// var parsed = new Gs1ScanResult();
// //var parsed = "";
// var raw = rawInput.Trim();
// bool hasParsedAis = !string.IsNullOrWhiteSpace(parsed.Lot)
// || parsed.ExpirationDate.HasValue
// || !string.IsNullOrWhiteSpace(parsed.Serial)
// || !string.IsNullOrWhiteSpace(parsed.Variant); // incluir (22)
// string? gtinToSend = parsed.Gtin ?? parsed.Variant; // (22) como fallback
// if (gtinToSend is null && !hasParsedAis && IsPlainCode(raw))
// gtinToSend = raw; // código plano tipeado (factory/regulatory)
// // 3. Armar parámetros de búsqueda
// var sp = new StockItemParsedSearchParams
// {
// Gtin = gtinToSend,
// Batch = string.IsNullOrWhiteSpace(parsed.Lot) ? null : parsed.Lot,
// Expiration = parsed.ExpirationDate.HasValue
// ? DateOnly.FromDateTime(parsed.ExpirationDate.Value)
// : null,
// Serial = string.IsNullOrWhiteSpace(parsed.Serial) ? null : parsed.Serial,
// LocationId = locationId,
// Page = 1,
// PageSize = 10
// };
// // 4. Log para depuración (quitar en producción)
// Console.WriteLine($"[ParseAndMatchAsync] Gtin={sp.Gtin}, Batch={sp.Batch}, Exp={sp.Expiration}, Serial={sp.Serial}, Loc={sp.LocationId}");
// // 5. Llamar a la API
// var resp = await _http.PostAsJsonAsync("/api/lsstockscan/search-parsed", sp);
// if (!resp.IsSuccessStatusCode)
// {
// var err = await resp.Content.ReadAsStringAsync();
// Console.WriteLine($"[ParseAndMatchAsync] API devolvió error {resp.StatusCode}: {err}");
// return null;
// }
// // 6. Leer resultado
// var pr = await resp.Content.ReadFromJsonAsync<PagedResult<StockItemScanResultDto>>();
// var first = pr?.Items?.FirstOrDefault();
// if (first == null)
// {
// Console.WriteLine("[ParseAndMatchAsync] No se encontró ningún ítem que coincida.");
// return null;
// }
// // 7. Mapear a DTO de selección
// return new StockItemSelectionDto
// {
// StockItemId = first.StockItemId,
// ProductId = first.ProductId,
// ProductName = first.ProductName,
// Batch = first.Batch ?? string.Empty,
// Expiration = first.Expiration?.ToDateTime(TimeOnly.MinValue),
// Quantity = first.AvailableQty,
// LocationId = first.LocationId ?? 0
// };
// }
// catch (Exception ex)
// {
// Console.WriteLine($"[ParseAndMatchAsync] Error inesperado: {ex}");
// throw;
// }
//}
//private static bool IsPlainCode(string s)
//{
// // sin FNC1 ($), sin espacios y sin prefijos AI típicos
// if (s.Contains('$') || s.Contains((char)29) || s.Contains(' ')) return false;
// // evita raws que empiezan como AIs "01","10","17","21","22"
// var prefix = s.Length >= 2 ? s[..2] : s;
// if (prefix is "01" or "10" or "11" or "17" or "21" or "22") return false;
// // permite letras/dígitos y algunos separadores comunes
// return s.All(c => char.IsLetterOrDigit(c) || c is '-' or '/' or '_');
//}
}