Files

57 lines
3.1 KiB
C#

using Net.Business.Entities.WMS.Transferencia;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Net.Data.WMS.Transferencia
{
// Elige la Entrada de Mercaderia de una Factura de Reserva que corresponde a una transferencia desde ALM99.
// WMS recibe por partes: cada entrada tiene su propio juego de articulos/cantidades, y WMS notifica una
// transferencia por entrada con ese mismo juego (se compara solo ItemCode y cantidad, no el numero de item).
// Reglas: coincidencia exacta de articulos y cantidades (sumadas por articulo); entre las que coinciden se toma la mas antigua
// (menor DocEntry) sin transferencia; si todas las que coinciden ya estan transferidas se rechaza para no duplicar.
// Ver docs/TRANSFERENCIA_IMPORTACION.md.
public static class EntradaImportacion
{
private const decimal Tolerancia = 0.0001m;
// Devuelve el DocEntry de la entrada elegida, o 0 con el motivo en "error".
public static int Elegir(string docNumFactura, List<BE_EntradaImportacionLinea> filas, List<BE_TransferenciaDetalle> detalle, out string error)
{
error = null;
var pedido = (detalle ?? new List<BE_TransferenciaDetalle>())
.GroupBy(x => x.CodigoArticulo)
.ToDictionary(g => g.Key, g => g.Sum(x => x.CantidadPedida));
var entradas = filas.GroupBy(x => x.DocEntry).OrderBy(g => g.Key).ToList();
var coincidentes = entradas.Where(g => Coincide(g, pedido)).ToList();
// La mas antigua que aun no tenga transferencia
var libre = coincidentes.FirstOrDefault(g => !g.Any(l => l.TransferenciaDocEntry > 0));
if (libre != null)
{
return libre.Key;
}
if (coincidentes.Count > 0)
{
var detalleYa = coincidentes.Select(g => $"entrada {g.First().DocNum} (DocEntry {g.Key}) ya transferida en la transferencia {g.First(l => l.TransferenciaDocEntry > 0).TransferenciaDocEntry}");
error = $"SAP: Todas las entradas de la factura de reserva {docNumFactura} con esos articulos y cantidades ya estan transferidas: {string.Join("; ", detalleYa)}";
return 0;
}
var pendientes = entradas.Where(g => !g.Any(l => l.TransferenciaDocEntry > 0)).Select(g => $"{g.First().DocNum}");
error = $"SAP: Ninguna entrada de la factura de reserva {docNumFactura} coincide con los articulos y cantidades enviados. " +
$"Entradas pendientes de transferir (DocNum): {(pendientes.Any() ? string.Join(", ", pendientes) : "ninguna")}";
return 0;
}
private static bool Coincide(IGrouping<int, BE_EntradaImportacionLinea> entrada, Dictionary<string, decimal> pedido)
{
var enEntrada = entrada.GroupBy(x => x.ItemCode).ToDictionary(g => g.Key, g => g.Sum(x => x.Quantity));
if (enEntrada.Count != pedido.Count) return false;
return enEntrada.All(kv => pedido.TryGetValue(kv.Key, out decimal cant) && Math.Abs(cant - kv.Value) <= Tolerancia);
}
}
}