feat: grafico mais vendido dinamico com filtro de periodo

This commit is contained in:
2025-01-17 22:14:51 -03:00
parent c7bc44aa54
commit 89a4d0e4be
8 changed files with 146 additions and 80 deletions

Binary file not shown.

View File

@@ -29,34 +29,32 @@ RRB&C - DashBoard
<body> <body>
<h1>DashBoard</h1> <h1>DashBoard</h1>
<!-- <form class="grid-container" > --> <div class="grid-container">
<input id="data-start" name="data-start" type="date"> <input id="data-start" name="data-start" oninput="mediaCuisine()" type="date">
<input id="data-end" name="data-end" type="date"> <input id="data-end" name="data-end" oninput="mediaCuisine()" type="date">
<!-- <input type="submit"> --> <!-- <button onclick="mediaCuisine()" >Filtrar</button> -->
<button onclick="mediaCuisine()" >Filtrar</button> </div>
<!-- </form> -->
<div class="grid-container"> <div class="grid-container">
<div class="card"> <div class="card">
<h4> Valor de Pagamentos </h4> <h4> Valor de Pagamentos </h4>
<h5>R$ {{total_pagamentos |floatformat:2 }} </h5> <h5 id="total-pagamentos">R$ {{total_pagamentos |floatformat:2 }} </h5>
<hr> <hr>
<h4> Quantidade de Pagamentos </h4> <h4> Quantidade de Pagamentos </h4>
<h5> {{ qdt_pagamentos }} </h5> <h5 id="qtd-pagamentos"> {{ qdt_pagamentos }} </h5>
<hr> <hr>
<h4> Ticket médio </h4> <h4> Ticket médio </h4>
<h5>R$ {{ ticekMedio |floatformat:2}} </h5> <h5 id="ticket-medio">R$ {{ ticekMedio |floatformat:2}} </h5>
<hr> <hr>
</div> </div>
<div class="card"> <div class="card">
<h4> Gráficos de vendas </h4> <h4> Gráficos de vendas </h4>
<div></div>
<canvas id="vendas" style="width:100%;height: 85%;max-width:100%; background-color: rgb(191, 225, 255);border-radius: 5px;"> <canvas id="vendas" style="width:100%;height: 85%;max-width:100%; background-color: rgb(191, 225, 255);border-radius: 5px;">
</canvas> </canvas>
</div> </div>
<div class="card"> <div class="card">
<h4> Gráficos cozinha </h4> <h4> Gráficos cozinha </h4>
<div></div> <div></div>
@@ -64,22 +62,7 @@ RRB&C - DashBoard
</canvas> </canvas>
</div> </div>
<div class="card">
<h4> Mais Vendidos </h4>
<table style="background-color: rgba(0, 255, 255, 0);">
<tr style="background-color: rgba(0, 255, 255, 0);">
<th style="text-align: left;background-color: rgba(0, 255, 255, 0.089);">Produto</th>
<th style="text-align: left;background-color: rgba(0, 255, 255, 0.075);">Quantidade</th>
</tr>
{% for produto in produtos_mais_vendidos %}
<tr>
<td id="n-{{forloop.counter0}}" style="background-color: rgba(0, 255, 255, 0);"> {{ produto.nome }} </td>
<td id="q-{{forloop.counter0}}" style="background-color: rgba(0, 255, 255, 0);"> {{ produto.quantidade }} </td>
</tr>
{% endfor %}
</table>
</div>

View File

@@ -7,6 +7,7 @@ from django.contrib.auth.models import User
from django.utils.dateparse import parse_datetime from django.utils.dateparse import parse_datetime
import datetime import datetime
import json
@@ -17,17 +18,7 @@ from gestaoRaul.decorators import group_required
@group_required(groupName='Gerente') @group_required(groupName='Gerente')
def home(request): def home(request):
try:
total_pagamentos = Payments.objects.aggregate(total=Sum('value'))['total']
qdt_pagamentos = Payments.objects.aggregate(total=Count('value'))['total']
pagamentos = Payments.objects.all()
ticekMedio = total_pagamentos / qdt_pagamentos
produtos_mais_vendidos = ProductComanda.objects.values('product').annotate(
quantidade=Count('product'),
nome=F('product__name') ).order_by('-quantidade')[:5]
return render(request, 'home.html', {'total_pagamentos': total_pagamentos, 'pagamentos': pagamentos, 'qdt_pagamentos': qdt_pagamentos, 'produtos_mais_vendidos': produtos_mais_vendidos, 'ticekMedio': ticekMedio, })
except:
return render(request, 'home.html') return render(request, 'home.html')
@@ -39,13 +30,41 @@ def chartCuisine(request,dateStart,dateEnd):
except: except:
dateStart = parse_datetime('2025-01-01 07:00:00') dateStart = parse_datetime('2025-01-01 07:00:00')
dateEnd = datetime.datetime.now() dateEnd = datetime.datetime.now()
# print(request.user.groups.all())
# print(request.user.is_authenticated)
# fulano = User()
tFila = [] tFila = []
tPreparando = [] tPreparando = []
tFinalizado = [] tFinalizado = []
total_pagamentos = Payments.objects.filter(datetime__range=(dateStart, dateEnd)).aggregate(total=Sum('value'))['total']
total_pagamentos = 0 if total_pagamentos is None else total_pagamentos
qdt_pagamentos = Payments.objects.filter(datetime__range=(dateStart, dateEnd)).aggregate(total=Count('value'))['total']
qdt_pagamentos = 0 if qdt_pagamentos is None else qdt_pagamentos
try:
ticket_medio = total_pagamentos / qdt_pagamentos
except:
ticket_medio = 0
try:
produtos_mais_vendidos = ProductComanda.objects.filter(
data_time__range=(dateStart, dateEnd)
).values('product').annotate(
quantidade=Count('product'),
nome=F('product__name')
).order_by('-quantidade')[:5]
maisVendidos = {}
for produto in produtos_mais_vendidos:
maisVendidos[produto['nome']] = produto['quantidade']
produtos_mais_vendidos = maisVendidos
except:
produtos_mais_vendidos = {
'petra': 25,
'petra2': 26,
'petra3': 27,
'petra4': 28,
'petra5': 29,
}
orders = Order.objects.filter(delivered__isnull=False, queue__gt=dateStart, queue__lt=dateEnd) orders = Order.objects.filter(delivered__isnull=False, queue__gt=dateStart, queue__lt=dateEnd)
try: try:
for order in orders: for order in orders:
@@ -61,10 +80,18 @@ def chartCuisine(request,dateStart,dateEnd):
'mediaFila': mediaFila, 'mediaFila': mediaFila,
'mediaPreparando': mediaPreparando, 'mediaPreparando': mediaPreparando,
'mediaFinalizado': mediaFinalizado, 'mediaFinalizado': mediaFinalizado,
'total_pagamentos': round(total_pagamentos, 2),
'qtd_pagamentos': qdt_pagamentos,
'ticket_medio': round(ticket_medio, 2),
'produtos_mais_vendidos': produtos_mais_vendidos,
}) })
except: except:
return JsonResponse({ return JsonResponse({
'mediaFila': 0, 'mediaFila': 0,
'mediaPreparando': 0, 'mediaPreparando': 0,
'mediaFinalizado': 0, 'mediaFinalizado': 0,
'total_pagamentos': round(total_pagamentos, 2),
'qtd_pagamentos': qdt_pagamentos,
'ticket_medio': round(ticket_medio, 2),
'produtos_mais_vendidos': produtos_mais_vendidos,
}) })

View File

@@ -1,4 +1,55 @@
var barColors = ["red", "green","blue","orange","brown"];
var chartVendas = new Chart("vendas", {
type: "bar",
data: {
labels: [],
datasets: [{
data: [],
backgroundColor: barColors,
}]
},
options: {
legend: {display: false},
title: {
display: true,
text: "Produtos mais vendidos"
},
}
});
var chartCuisine = new Chart("cuisine", {
type: "doughnut",
data: {
labels: [],
datasets: [{
backgroundColor: barColors,
data: []
}]
},
options: {
legend: {display: true},
title: {
display: true,
text: "Tempo médio (em minutos) do pedido em cada etapa."
},
}
});
function getDataAtualFormatada() {
const data = new Date();
const ano = data.getFullYear();
const mes = String(data.getMonth() + 1).padStart(2, '0'); // Mês começa em 0
const dia = String(data.getDate()).padStart(2, '0');
const dataFormatada = `${ano}-${mes}-${dia}`;
return dataFormatada;
}
function productsPlus(){ function productsPlus(){
@@ -16,33 +67,35 @@ var yValues = [document.getElementById('q-0').innerText,
]; ];
var barColors = ["red", "green","blue","orange","brown"]; var barColors = ["red", "green","blue","orange","brown"];
new Chart("vendas", { // new Chart("vendas", {
type: "bar", // type: "bar",
data: { // data: {
labels: xValues, // labels: xValues,
datasets: [{ // datasets: [{
backgroundColor: barColors, // backgroundColor: barColors,
data: yValues // data: yValues
}] // }]
}, // },
options: { // options: {
legend: {display: false}, // legend: {display: false},
title: { // title: {
display: true, // display: true,
text: "Produtos mais vendidos" // text: "Produtos mais vendidos"
}, // },
} // }
}); // });
} }
function mediaCuisine(){ function mediaCuisine(){
var dateStart = document.getElementById('data-start').value == '' ? '2025-01-01' :document.getElementById('data-start').value; var dateStart = document.getElementById('data-start').value == '' ? '2025-01-01' :document.getElementById('data-start').value;
var dateEnd = document.getElementById('data-end').value == '' ? '2025-01-15' :document.getElementById('data-end').value;; var dateEnd = document.getElementById('data-end').value == '' ? getDataAtualFormatada() :document.getElementById('data-end').value;;
var yValues = []; var yValues = [];
var xValues = ['Fila', 'Preparando', 'Entregar']; var xValues = ['Fila', 'Preparando', 'Entregar'];
var barColors = ["red", "green","blue","orange","brown"]; var totalPagamenstos = document.getElementById('total-pagamentos')
var qtdPagamentos = document.getElementById('qtd-pagamentos')
var ticketMedio = document.getElementById('ticket-medio')
var resposta = fetch(`/chartCuisine/${dateStart}/${dateEnd}`, {method: 'GET', var resposta = fetch(`/chartCuisine/${dateStart}/${dateEnd}`, {method: 'GET',
headers: {'Content-Type': 'application/json', headers: {'Content-Type': 'application/json',
@@ -53,36 +106,39 @@ var resposta = fetch(`/chartCuisine/${dateStart}/${dateEnd}`, {method: 'GET',
yValues.push(data['mediaFila']) yValues.push(data['mediaFila'])
yValues.push(data['mediaPreparando']) yValues.push(data['mediaPreparando'])
yValues.push(data['mediaFinalizado']) yValues.push(data['mediaFinalizado'])
console.log(yValues) var totalP = data['total_pagamentos'] ?? '0,00'
new Chart("cuisine", { var qtdP = data['qtd_pagamentos'] ?? '0'
type: "doughnut", var tocketP = data['ticket_medio'] ?? '0'
data: { qtdPagamentos.innerText = qtdP
labels: xValues, totalPagamenstos.innerText = 'R$ ' + totalP
datasets: [{ ticketMedio.innerText = 'R$ ' + tocketP
backgroundColor: barColors, var produtos_mais_vendidos = data.produtos_mais_vendidos
data: yValues
}] var chaves = Object.keys(produtos_mais_vendidos);
}, var valores = [];
options: {
legend: {display: true}, for (const chave of chaves) {
title: { valores.push(produtos_mais_vendidos[chave]);
display: true, }
text: "Tempo médio (em minutos) do pedido em cada etapa."
}, chartVendas.data.datasets[0].data = valores
} chartVendas.data.labels = chaves
}); chartVendas.update();
chartCuisine.data.datasets[0].data = yValues
chartCuisine.data.labels = xValues
chartCuisine.update();
}) })
.catch(error => { .catch(error => {
alert('Erro ao trazer dados da cozinha:', error) alert('Erro ao trazer dados da cozinha:', error)
console.error('Erro ao trazer dados da cozinha:', error); console.error('Erro ao trazer dados da cozinha:', error);
}); });
} }
function deleyGraficos(){ function deleyGraficos(){
setTimeout(function() { setTimeout(function() {
mediaCuisine();}, 20000); mediaCuisine();}, 20000);
} }
// productsPlus()
mediaCuisine() mediaCuisine()
// console.log(document.getElementById('data-start').value)