diff --git a/.gitignore b/.gitignore index 0582183..54687ca 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ dev_home gestaoRaul/static .env gestaoRaul/db.sqlite3 +duplicati_backups + diff --git a/gestaoRaul/clients/__pycache__/views.cpython-312.pyc b/gestaoRaul/clients/__pycache__/views.cpython-312.pyc index c6f6d26..c419774 100644 Binary files a/gestaoRaul/clients/__pycache__/views.cpython-312.pyc and b/gestaoRaul/clients/__pycache__/views.cpython-312.pyc differ diff --git a/gestaoRaul/clients/templates/clients.html b/gestaoRaul/clients/templates/clients.html index 7baa309..b756fd0 100644 --- a/gestaoRaul/clients/templates/clients.html +++ b/gestaoRaul/clients/templates/clients.html @@ -51,16 +51,7 @@ Clientes -
- {% csrf_token %} - - -
+ diff --git a/gestaoRaul/clients/templates/viewclient.html b/gestaoRaul/clients/templates/viewclient.html index f4fdeae..44d5b53 100644 --- a/gestaoRaul/clients/templates/viewclient.html +++ b/gestaoRaul/clients/templates/viewclient.html @@ -16,7 +16,12 @@ Comandas

{{client.name}}

-

R$ {{client.id | totalFiado}}

+

R$ {{client.id | totalFiado}}


+

R$

+
@@ -26,6 +31,7 @@ Comandas Atendente Data abertura Data fechamento + Detalhes Valor @@ -35,6 +41,7 @@ Comandas {{comanda.user.first_name}} {{comanda.user.last_name}} {{comanda.dt_open}} {{comanda.dt_close}} + @@ -57,6 +64,7 @@ Comandas + {% endblock %} \ No newline at end of file diff --git a/gestaoRaul/clients/views.py b/gestaoRaul/clients/views.py index 97d513c..bc29762 100644 --- a/gestaoRaul/clients/views.py +++ b/gestaoRaul/clients/views.py @@ -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') \ No newline at end of file + 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) \ No newline at end of file diff --git a/gestaoRaul/comandas/__pycache__/models.cpython-312.pyc b/gestaoRaul/comandas/__pycache__/models.cpython-312.pyc index 64eac19..ccdf436 100644 Binary files a/gestaoRaul/comandas/__pycache__/models.cpython-312.pyc and b/gestaoRaul/comandas/__pycache__/models.cpython-312.pyc differ diff --git a/gestaoRaul/comandas/__pycache__/views.cpython-312.pyc b/gestaoRaul/comandas/__pycache__/views.cpython-312.pyc index f69aad3..97d21b8 100644 Binary files a/gestaoRaul/comandas/__pycache__/views.cpython-312.pyc and b/gestaoRaul/comandas/__pycache__/views.cpython-312.pyc differ diff --git a/gestaoRaul/comandas/models.py b/gestaoRaul/comandas/models.py index ee79a2d..4b853c0 100644 --- a/gestaoRaul/comandas/models.py +++ b/gestaoRaul/comandas/models.py @@ -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 \ No newline at end of file + return self.comanda.name + " - " + self.product.name + + diff --git a/gestaoRaul/comandas/views.py b/gestaoRaul/comandas/views.py index 57b065e..b2329b9 100644 --- a/gestaoRaul/comandas/views.py +++ b/gestaoRaul/comandas/views.py @@ -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): diff --git a/gestaoRaul/db.sqlite3 b/gestaoRaul/db.sqlite3 index c5ed319..9c8c9f3 100644 Binary files a/gestaoRaul/db.sqlite3 and b/gestaoRaul/db.sqlite3 differ diff --git a/gestaoRaul/gestaoRaul/__pycache__/settings.cpython-312.pyc b/gestaoRaul/gestaoRaul/__pycache__/settings.cpython-312.pyc index d951cec..75a8458 100644 Binary files a/gestaoRaul/gestaoRaul/__pycache__/settings.cpython-312.pyc and b/gestaoRaul/gestaoRaul/__pycache__/settings.cpython-312.pyc differ diff --git a/gestaoRaul/payments/__pycache__/models.cpython-312.pyc b/gestaoRaul/payments/__pycache__/models.cpython-312.pyc index d08d87e..d0cb77a 100644 Binary files a/gestaoRaul/payments/__pycache__/models.cpython-312.pyc and b/gestaoRaul/payments/__pycache__/models.cpython-312.pyc differ diff --git a/gestaoRaul/payments/models.py b/gestaoRaul/payments/models.py index c5b4d0d..c9832e1 100644 --- a/gestaoRaul/payments/models.py +++ b/gestaoRaul/payments/models.py @@ -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 \ No newline at end of file + 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 \ No newline at end of file diff --git a/gestaoRaul/templates/static/clients/js/clients.js b/gestaoRaul/templates/static/clients/js/clients.js index 151e59e..38ca6c5 100644 --- a/gestaoRaul/templates/static/clients/js/clients.js +++ b/gestaoRaul/templates/static/clients/js/clients.js @@ -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 = ' 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 = ' 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); \ No newline at end of file