fix: conexão com api de pagamento de multiplas comandas ok

This commit is contained in:
2025-06-22 17:19:18 -03:00
parent 0e7c7d7c68
commit 179342ff80
14 changed files with 281 additions and 38 deletions

2
.gitignore vendored
View File

@@ -5,3 +5,5 @@ dev_home
gestaoRaul/static gestaoRaul/static
.env .env
gestaoRaul/db.sqlite3 gestaoRaul/db.sqlite3
duplicati_backups

View File

@@ -51,16 +51,7 @@ Clientes
<input type="hidden" id="name-{{client.id}}" value="{{ client.name }}"> <input type="hidden" id="name-{{client.id}}" value="{{ client.name }}">
<input type="hidden" id="contact-{{client.id}}" value="{{ client.contact }}"> <input type="hidden" id="contact-{{client.id}}" value="{{ client.contact }}">
<form style="max-width: 50px;" hx-post="{% url 'payDebt' %}" hx-trigger="click" hx-target="#client-list">
{% csrf_token %}
<input type="hidden" name="id-client" id="id-{{client.id}}" value="{{ client.id }}">
<button style="background-color: rgba(255, 0, 0, 0); padding: 0px; border: none;">
<img
src="{% static 'midia/icons/pay.svg' %}"
style="width: 35px; height: 35px; cursor: pointer;">
</img>
</button>
</form>
</div> </div>
</td> </td>

View File

@@ -16,7 +16,12 @@ Comandas
<body> <body>
<div style="justify-self: center;"> <div style="justify-self: center;">
<h4>{{client.name}}</h4> <h4>{{client.name}}</h4>
<h4>R$ {{client.id | totalFiado}}</h4> <h4>R$ {{client.id | totalFiado}}</h4><br>
<h4 id="total-selecionado">R$</h4>
<button id="btn-fechar-comandas" class="btn-fechar" onclick="enviarComandasSelecionadas()">
<span class="icon"></span>
Fechar Comandas Selecionadas
</button>
</div> </div>
<div class=" "> <div class=" ">
@@ -26,6 +31,7 @@ Comandas
<th style="text-align: left;"><b>Atendente</b></th> <th style="text-align: left;"><b>Atendente</b></th>
<th style="text-align: left;"><b>Data abertura</b></th> <th style="text-align: left;"><b>Data abertura</b></th>
<th style="text-align: left;"><b>Data fechamento</b></th> <th style="text-align: left;"><b>Data fechamento</b></th>
<th style="text-align: left;"><b><input id="selectAll" name="selectAll" type="checkbox"></b></th>
<th style="text-align: left;"><b>Detalhes</b></th> <th style="text-align: left;"><b>Detalhes</b></th>
<th style="text-align: left;"><b>Valor</b></th> <th style="text-align: left;"><b>Valor</b></th>
</tr> </tr>
@@ -35,6 +41,7 @@ Comandas
<td>{{comanda.user.first_name}} {{comanda.user.last_name}}</td> <td>{{comanda.user.first_name}} {{comanda.user.last_name}}</td>
<td>{{comanda.dt_open}}</td> <td>{{comanda.dt_open}}</td>
<td>{{comanda.dt_close}}</td> <td>{{comanda.dt_close}}</td>
<td><input id="{{comanda.id}}" name="{{comanda.id}}" type="checkbox"></td>
<td> <td>
<span data-tooltip="Visualizar Comanda" data-flow="top"> <span data-tooltip="Visualizar Comanda" data-flow="top">
<a href="{% url 'viewcomanda' %}?parametro={{ comanda.id }}"> <a href="{% url 'viewcomanda' %}?parametro={{ comanda.id }}">
@@ -57,6 +64,7 @@ Comandas
</body> </body>
<script src="{% static 'comandas/js/comandas.js' %}"></script> <script src="{% static 'comandas/js/comandas.js' %}"></script>
<script src="{% static 'clients/js/clients.js' %}"></script>
{% endblock %} {% endblock %}

View File

@@ -1,11 +1,19 @@
from decimal import Decimal from decimal import Decimal
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.http import JsonResponse
from django.views.decorators.http import require_POST
from django.views.decorators.csrf import csrf_exempt
import json
from comandas.models import Comanda, ProductComanda from comandas.models import Comanda, ProductComanda
from gestaoRaul.decorators import group_required from gestaoRaul.decorators import group_required
from clients.models import Client from clients.models import Client
from payments.models import Payments from payments.models import Payments, somar
from typePay.models import TypePay
# Create your views here.
@@ -56,10 +64,48 @@ def editClient(request):
client.save() client.save()
return redirect('/clients') return redirect('/clients')
@csrf_exempt
@require_POST
def payDebt(request): def payDebt(request):
# id = request.POST.get('id-client') try:
# client_id = int(id) # Verifica se é uma requisição AJAX
# client = Client.objects.get(id=client_id) if not request.headers.get('X-Requested-With') == 'XMLHttpRequest':
# client.debt = client.debt - 1 return JsonResponse({'error': 'Requisição inválida'}, status=400)
# client.save()
return redirect('/clients') # Obter os IDs do corpo da requisição (não mais da URL)
try:
data = json.loads(request.body)
comanda_ids = data.get('ids', [])
except json.JSONDecodeError:
return JsonResponse({'error': 'JSON inválido'}, status=400)
for comanda_id in comanda_ids:
try:
comanda = Comanda.objects.get(id=comanda_id)
comanda.status = 'CLOSED'
comanda.save()
typePayment = TypePay.objects.get(id=1)
consumo = ProductComanda.objects.filter(comanda=comanda_id)
value = somar(consumo,comanda)
print(value["totalSemTaxa"])
description = 'PAGAMENTO DE FIADO'
pagamento = Payments(value=value["totalSemTaxa"], comanda=comanda, type_pay=typePayment,description=description,client=comanda.client)
pagamento.save()
except Comanda.DoesNotExist:
return JsonResponse({'error': f'Comanda com ID {comanda_id} não encontrada'}, status=404)
return redirect(f'/clients/viewClient/{comanda.client.id}')
# return JsonResponse({
# 'success': True,
# 'message': f'{len(comanda_ids)} comandas processadas',
# 'ids': comanda_ids
# }, status=200)
except Exception as e:
return JsonResponse({
'success': False,
'error': str(e)
}, status=500)

View File

@@ -2,10 +2,12 @@ from django.db import models
from django.contrib.auth.models import User from django.contrib.auth.models import User
from clients.models import Client from clients.models import Client
from products.models import Product from products.models import Product
from mesas.models import Mesa from mesas.models import Mesa
from typePay.models import TypePay from typePay.models import TypePay
# from payments.models import Payments
class Comanda(models.Model): class Comanda(models.Model):
id = models.AutoField(primary_key=True) id = models.AutoField(primary_key=True)
@@ -27,4 +29,6 @@ class ProductComanda(models.Model):
product = models.ForeignKey(Product, on_delete=models.PROTECT) product = models.ForeignKey(Product, on_delete=models.PROTECT)
applicant = models.CharField(max_length=255, null=True, blank=True) applicant = models.CharField(max_length=255, null=True, blank=True)
def __str__(self) -> str: def __str__(self) -> str:
return self.comanda.name + " - " + self.product.name return self.comanda.name + " - " + self.product.name

View File

@@ -9,7 +9,7 @@ from django.db.models import Count, F
from comandas.models import Comanda, ProductComanda from comandas.models import Comanda, ProductComanda
from clients.models import Client from clients.models import Client
from payments.models import Payments from payments.models import Payments, somar
from orders.models import Order from orders.models import Order
from products.models import Product from products.models import Product
from mesas.models import Mesa from mesas.models import Mesa
@@ -23,22 +23,22 @@ def comandas(request):
return render(request, 'comandas.html', {'comandas': comandas, 'mesas': mesas}) return render(request, 'comandas.html', {'comandas': comandas, 'mesas': mesas})
def somar(consumo:ProductComanda, comanda:Comanda): # def somar(consumo:ProductComanda, comanda:Comanda):
parcial = Payments.objects.filter(comanda=comanda) # parcial = Payments.objects.filter(comanda=comanda)
totalParcial = Decimal(0) # totalParcial = Decimal(0)
total:Decimal = Decimal(0) # total:Decimal = Decimal(0)
for p in parcial: # for p in parcial:
totalParcial += p.value # totalParcial += p.value
for produto in consumo: # for produto in consumo:
total += Decimal(produto.product.price) # total += Decimal(produto.product.price)
valores = { # valores = {
'total':total, # 'total':total,
'parcial':totalParcial, # 'parcial':totalParcial,
'taxa': round(total * Decimal(0.1), 2), # 'taxa': round(total * Decimal(0.1), 2),
'totalSemTaxa':total - totalParcial, # 'totalSemTaxa':total - totalParcial,
'totalComTaxa': round((total - totalParcial)+(total * Decimal(0.1)),2) # 'totalComTaxa': round((total - totalParcial)+(total * Decimal(0.1)),2)
} # }
return valores # return valores
@group_required(groupName='Garçom') @group_required(groupName='Garçom')
def viewComanda(request): def viewComanda(request):

Binary file not shown.

View File

@@ -1,6 +1,8 @@
from django.db import models from django.db import models
from decimal import Decimal
from typePay.models import TypePay from typePay.models import TypePay
from comandas.models import Comanda from comandas.models import Comanda, ProductComanda
from clients.models import Client from clients.models import Client
@@ -15,4 +17,22 @@ class Payments(models.Model):
def __str__(self): def __str__(self):
return self.comanda.name return self.comanda.name
def somar(consumo:ProductComanda, comanda:Comanda):
parcial = Payments.objects.filter(comanda=comanda)
totalParcial = Decimal(0)
total:Decimal = Decimal(0)
for p in parcial:
totalParcial += p.value
for produto in consumo:
total += Decimal(produto.product.price)
valores = {
'total':total,
'parcial':totalParcial,
'taxa': round(total * Decimal(0.1), 2),
'totalSemTaxa':total - totalParcial,
'totalComTaxa': round((total - totalParcial)+(total * Decimal(0.1)),2)
}
return valores

View File

@@ -51,3 +51,175 @@ function editclient(id) {
} }
function calcularTotalSelecionado() {
let total = 0;
// Seleciona todos os checkboxes marcados (exceto o "selectAll")
const checkboxes = document.querySelectorAll('input[type="checkbox"]:checked:not(#selectAll)');
checkboxes.forEach(checkbox => {
const row = checkbox.closest('tr');
const valorCell = row.querySelector('td:nth-child(7)'); // 7ª coluna é o valor
if (valorCell) {
const valorText = valorCell.textContent.trim();
// Remove possíveis formatações de moeda e converte para número
const valor = parseFloat(
valorText
.replace('.',',')
.replace(/[^\d,]/g, '')
.replace(',', '.')
);
if (!isNaN(valor)) {
total += valor;
}
}
});
console.log(total)
// Exibe o total na tela (você pode ajustar onde mostrar)
const totalElement = document.getElementById('total-selecionado');
if (totalElement) {
totalElement.textContent = total.toLocaleString('pt-BR', {style: 'currency', currency: 'BRL'});
} else {
// Cria um elemento para mostrar o total se não existir
const display = document.createElement('div');
display.id = 'total-selecionado';
display.style.margin = '10px';
display.style.fontWeight = 'bold';
display.textContent = `Total selecionado: ${total.toLocaleString()}`;
document.querySelector('table').insertAdjacentElement('afterend', display);
}
return total;
}
// Adiciona evento de change a todos os checkboxes
document.addEventListener('DOMContentLoaded', function() {
const checkboxes = document.querySelectorAll('input[type="checkbox"]');
checkboxes.forEach(checkbox => {
checkbox.addEventListener('change', calcularTotalSelecionado);
});
});
document.addEventListener('DOMContentLoaded', function() {
const selectAll = document.getElementById('selectAll');
if (selectAll) {
selectAll.addEventListener('change', function() {
const isChecked = this.checked;
const checkboxes = document.querySelectorAll('input[type="checkbox"]:not(#selectAll)');
checkboxes.forEach(checkbox => {
checkbox.checked = isChecked;
});
// Dispara o evento para calcular o total
calcularTotalSelecionado();
});
}
// Adiciona evento para desmarcar "selectAll" se algum checkbox for desmarcado
const checkboxes = document.querySelectorAll('input[type="checkbox"]:not(#selectAll)');
checkboxes.forEach(checkbox => {
checkbox.addEventListener('change', function() {
if (!this.checked && selectAll.checked) {
selectAll.checked = false;
}
});
});
});
async function enviarComandasSelecionadas() {
const btn = document.getElementById('btn-fechar-comandas');
const feedback = document.getElementById('api-feedback');
btn.disabled = true;
btn.innerHTML = '<span class="icon">⏳</span> Processando...';
try {
const checkboxes = document.querySelectorAll('input[type="checkbox"]:checked:not(#selectAll)');
const ids = [];
checkboxes.forEach(checkbox => {
const id = checkbox.id;
if (/^\d+$/.test(id)) {
ids.push(parseInt(id));
}
});
if (ids.length === 0) {
feedback.textContent = 'Nenhuma comanda válida selecionada.';
feedback.className = 'feedback-message error';
return;
}
const response = await fetch('http://192.168.1.150:8001/clients/payDebt', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
'X-CSRFToken': getCookie('csrftoken'),
},
body: JSON.stringify({ ids: ids })
});
// Verifica se a resposta é JSON válido
const text = await response.text();
let data;
try {
data = JSON.parse(text);
} catch (e) {
throw new Error(`Resposta inválida do servidor: ${text.substring(0, 100)}...`);
}
if (!response.ok) {
throw new Error(data.error || `Erro HTTP: ${response.status}`);
}
feedback.textContent = data.message || `${ids.length} comandas processadas com sucesso!`;
feedback.className = 'feedback-message success';
setTimeout(() => {
window.location.reload();
}, 2000);
} catch (error) {
console.error('Erro:', error);
feedback.textContent = error.message || 'Erro ao processar comandas. Verifique o console para mais detalhes.';
feedback.className = 'feedback-message error';
} finally {
btn.disabled = false;
btn.innerHTML = '<span class="icon">✓</span> Fechar Comandas Selecionadas';
}
}
// Função auxiliar para pegar o token CSRF
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
// Exemplo de como chamar a função (pode ser vinculada a um botão)
// document.getElementById('btn-fechar-comandas').addEventListener('click', enviarComandasSelecionadas);