miércoles, mayo 21, 2014

jQueryFlot en ASP.net (II) + AJAX

Siguiendo con la entrada anterior, supongamos ahora que queremos actualizar los datos de la página en función de, por ejemplo, que se seleccione un rango de fechas u otro. Y clara está, esta actualización queremos hacerla sin tener que recargar la página, es decir, mediante AJAX. Tendremos que hacer las siguientes modificaciones:

  • Nueva función TopMarcasJson en el controlador VentasController que retorne un objeto de tipo JsonResult que será consumido directamente por la función $.plot desde la vista
  • Modificar la función Top del controlador VentasController para que pase la colección TopMarcas a la vista (será la vista la que vaya a buscar los datos del modelo con la función anterior).
  • Modificar la vista Ventas/Top para que la función $.plot tome los datos mediante AJAX.

Nueva función TopMarcasJson en VentasController

        /// <summary>
///
Retorna JSON que se consume mediante AJAX desde la función $.plot de la vista Ventas/Top
/// </summary>
/// <returns></returns>
[HttpGet]
public JsonResult TopMarcasJson(int año)
{
var currentUserId = User.Identity.GetUserId();
var currentUser = _userManager.FindById(User.Identity.GetUserId());
var currentUserZonas = currentUser.Zonas.Select(z => z.ZonaId);

var ventasPorMarca = _ctx.Ventas
.Where(v => v.Año == año)
.Where(v => currentUserZonas.Contains(v.Zona))
// Incluir sólo los de las zonas del comercial logado
.GroupBy(v => v.Marca)
.Select(v =>
new VentaMarcaViewModel()
{
Marca = v.FirstOrDefault().Marca,
Gama = v.FirstOrDefault().Gama,
Importe = v.Sum(g => g.Importe),
Cantidad = v.Sum(g => g.Cantidad)
})
.OrderByDescending(c => c.Importe);

// Top 10 ventas por marca
var topVentasPorMarca = ventasPorMarca
.Take(10)
// Top 10
.ToList();

// Resto: consolidar como uno sólo
var restoTopVentasPorMarca = ventasPorMarca
.Skip(10)
.Select(v =>
new { Marca = "Resto", v.Importe, v.Cantidad })
.GroupBy(v => v.Marca)
// Agrupar el resto
.Select(v => new VentaMarcaViewModel()
{
Marca =
"Resto",
Gama =
"",
Importe = v.Sum(g => g.Importe),
Cantidad = v.Sum(g => g.Cantidad)
})
.ToList()
// Lista con un único el elemento, el consolidado
.FirstOrDefault(); // Coge el primer (y único elemento).

// Añadir a top ventas el consolidado con el resto.
if (restoTopVentasPorMarca != null)
topVentasPorMarca.Add(restoTopVentasPorMarca);

// Convertir a Json de tipo array de {label, data}
return Json(
topVentasPorMarca.Select(v =>
new { label = v.Marca, data = v.Importe }),
JsonRequestBehavior.AllowGet
);
}

Modificar la función Top de VentasController


Ya no hará falta pasar la colección TopMarcas desde esta función, por lo que podemos suprimir el fragmento de código que hace referencia a eso y retornar la vista vacía (sin modelo).


Modificar script de la vista Ventas/Top


Debemos sustituir el fragmento bajo /** Recoger datos y dibujar **/ por el nuevo:

        function drawPieChart(placeholder, data0, position) {
$.getJSON(
"TopMarcasJson", function (data) {
//succes - data loaded, now use plot:
$.plot(placeholder, data, {
series: {
pie: {
show:
true,
tilt: 0.8,
highlight: {
opacity: 0.25
},
stroke: {
color:
'#fff',
width: 2
},
startAngle: 2
}
},
legend: {
show:
true,
position: position ||
"ne",
labelBoxBorderColor:
null,
margin: [-30, 15]
},
grid: {
hoverable:
true,
clickable:
true
}
})
            });
}
drawPieChart(placeholder);
Obsérvese cómo se llama a la función $.getJSON y el retorno obtenido se le pasa a $.plot.

No hay comentarios:

Publicar un comentario