mirror of
https://github.com/welton89/RRBEC.git
synced 2026-04-05 21:45:41 +00:00
feat: grafico mais vendido dinamico com filtro de periodo
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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)
|
|
||||||
Reference in New Issue
Block a user