mirror of
https://github.com/welton89/RRBEC.git
synced 2026-04-04 21:20:35 +00:00
fix: conexão com api de pagamento de multiplas comandas ok
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -5,3 +5,5 @@ dev_home
|
||||
gestaoRaul/static
|
||||
.env
|
||||
gestaoRaul/db.sqlite3
|
||||
duplicati_backups
|
||||
|
||||
|
||||
Binary file not shown.
@@ -51,16 +51,7 @@ Clientes
|
||||
<input type="hidden" id="name-{{client.id}}" value="{{ client.name }}">
|
||||
<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>
|
||||
|
||||
</td>
|
||||
|
||||
@@ -16,7 +16,12 @@ Comandas
|
||||
<body>
|
||||
<div style="justify-self: center;">
|
||||
<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 class=" ">
|
||||
@@ -26,6 +31,7 @@ Comandas
|
||||
<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 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>Valor</b></th>
|
||||
</tr>
|
||||
@@ -35,6 +41,7 @@ Comandas
|
||||
<td>{{comanda.user.first_name}} {{comanda.user.last_name}}</td>
|
||||
<td>{{comanda.dt_open}}</td>
|
||||
<td>{{comanda.dt_close}}</td>
|
||||
<td><input id="{{comanda.id}}" name="{{comanda.id}}" type="checkbox"></td>
|
||||
<td>
|
||||
<span data-tooltip="Visualizar Comanda" data-flow="top">
|
||||
<a href="{% url 'viewcomanda' %}?parametro={{ comanda.id }}">
|
||||
@@ -57,6 +64,7 @@ Comandas
|
||||
|
||||
</body>
|
||||
<script src="{% static 'comandas/js/comandas.js' %}"></script>
|
||||
<script src="{% static 'clients/js/clients.js' %}"></script>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
@@ -1,11 +1,19 @@
|
||||
from decimal import Decimal
|
||||
from django.shortcuts import render, redirect
|
||||
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 gestaoRaul.decorators import group_required
|
||||
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()
|
||||
return redirect('/clients')
|
||||
|
||||
|
||||
@csrf_exempt
|
||||
@require_POST
|
||||
def payDebt(request):
|
||||
# id = request.POST.get('id-client')
|
||||
# client_id = int(id)
|
||||
# client = Client.objects.get(id=client_id)
|
||||
# client.debt = client.debt - 1
|
||||
# client.save()
|
||||
return redirect('/clients')
|
||||
try:
|
||||
# Verifica se é uma requisição AJAX
|
||||
if not request.headers.get('X-Requested-With') == 'XMLHttpRequest':
|
||||
return JsonResponse({'error': 'Requisição inválida'}, status=400)
|
||||
|
||||
# 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)
|
||||
Binary file not shown.
Binary file not shown.
@@ -2,10 +2,12 @@ from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
|
||||
|
||||
from clients.models import Client
|
||||
from products.models import Product
|
||||
from mesas.models import Mesa
|
||||
from typePay.models import TypePay
|
||||
# from payments.models import Payments
|
||||
|
||||
class Comanda(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
@@ -27,4 +29,6 @@ class ProductComanda(models.Model):
|
||||
product = models.ForeignKey(Product, on_delete=models.PROTECT)
|
||||
applicant = models.CharField(max_length=255, null=True, blank=True)
|
||||
def __str__(self) -> str:
|
||||
return self.comanda.name + " - " + self.product.name
|
||||
return self.comanda.name + " - " + self.product.name
|
||||
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ from django.db.models import Count, F
|
||||
|
||||
from comandas.models import Comanda, ProductComanda
|
||||
from clients.models import Client
|
||||
from payments.models import Payments
|
||||
from payments.models import Payments, somar
|
||||
from orders.models import Order
|
||||
from products.models import Product
|
||||
from mesas.models import Mesa
|
||||
@@ -23,22 +23,22 @@ def comandas(request):
|
||||
return render(request, 'comandas.html', {'comandas': comandas, 'mesas': mesas})
|
||||
|
||||
|
||||
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
|
||||
# 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
|
||||
|
||||
@group_required(groupName='Garçom')
|
||||
def viewComanda(request):
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,6 +1,8 @@
|
||||
from django.db import models
|
||||
from decimal import Decimal
|
||||
|
||||
from typePay.models import TypePay
|
||||
from comandas.models import Comanda
|
||||
from comandas.models import Comanda, ProductComanda
|
||||
from clients.models import Client
|
||||
|
||||
|
||||
@@ -15,4 +17,22 @@ class Payments(models.Model):
|
||||
|
||||
|
||||
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
|
||||
@@ -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);
|
||||
Reference in New Issue
Block a user