diff --git a/GastoSystem b/GastoSystem new file mode 160000 index 00000000..815cd990 --- /dev/null +++ b/GastoSystem @@ -0,0 +1 @@ +Subproject commit 815cd99096464c65859518f75e997d2a6ea75ae2 diff --git a/expenses/forms.py b/expenses/forms.py index b617a3eb..5e541f5f 100644 --- a/expenses/forms.py +++ b/expenses/forms.py @@ -1,6 +1,6 @@ from django import forms from django.core.exceptions import ValidationError - +from expenses.admin import PaymentAdmin from expenses.models import Category class SelectCategoryForm(forms.Form): @@ -10,6 +10,47 @@ class SelectCategoryForm(forms.Form): from django.core.exceptions import ValidationError +from expenses.models import Category + +from expenses.models import Payment + +from expenses.models import Limit + +class CategoryForm(forms.ModelForm): + class Meta: + model = Category + fields = '__all__' + +class LimitForm(forms.ModelForm): + class Meta: + model = Limit + fields = ['year','month','value'] + labels = { + 'year': 'Ano', + 'month': 'Mês', + 'value': 'Valor', + } + year = forms.IntegerField(disabled=True) + month = forms.IntegerField(disabled=True) + + + +class PaymentForm(forms.ModelForm): + class Meta: + model = Payment + fields = ['description'] + +class EditExpenseForm(forms.ModelForm): + class Meta: + model = Expense + fields = ['category','payment','description','value','date'] + labels = { + 'category': 'Categoria', + 'payment': 'Pagamento', + 'description' : 'Descrição', + 'value' : 'Valor', + 'date' : 'data' + } class ExpenseForm(forms.ModelForm): class Meta: diff --git a/expenses/models.py b/expenses/models.py index 6f7f7d57..4a7c4c7a 100644 --- a/expenses/models.py +++ b/expenses/models.py @@ -50,6 +50,8 @@ class Meta: def __str__(self): return f'{self.category.description.upper()} -{self.description.upper()} ({self.value})' + + @staticmethod def list_expenses_by_category(category): from django.db.models import Sum @@ -58,7 +60,7 @@ def list_expenses_by_category(category): ).annotate(total=Sum('value')).order_by( '-date__year','-date__month' ) - + def clean(self): if self.value<0: raise ValidationError(f'''O valor '{self.value}' é inválido diff --git a/expenses/static/expenses/css/report-expense.css b/expenses/static/expenses/css/report-expense.css new file mode 100644 index 00000000..c263ca22 --- /dev/null +++ b/expenses/static/expenses/css/report-expense.css @@ -0,0 +1,13 @@ +.breadcamp{ + margin-left: 2em; +} + +.report-list{ + margin-top: 1em; + margin-left: 2em; +} + +.content-report{ + margin-left: 2em; + margin-top: 1em; +} \ No newline at end of file diff --git a/expenses/templates/base.html b/expenses/templates/base.html index e910ee0c..3dc85539 100644 --- a/expenses/templates/base.html +++ b/expenses/templates/base.html @@ -23,8 +23,10 @@ @@ -33,7 +35,7 @@ {% endblock %} @@ -45,6 +47,9 @@ $("#nav-report").click(function() { window.open("{% url 'expenses:report' %}","_self") }); + $("#nav-bank-loan").click(function() { + window.open("{% url 'expenses:bank_loan' %}","_self") + }); $("#nav-about").click(function() { window.open("{% url 'expenses:about' %}","_self") }); diff --git a/expenses/templates/expenses/bank-loan.html b/expenses/templates/expenses/bank-loan.html new file mode 100644 index 00000000..7c44371d --- /dev/null +++ b/expenses/templates/expenses/bank-loan.html @@ -0,0 +1,8 @@ +{% extends "base.html" %} +{% load static %} +{% block title %}Empréstimo Bancário{% endblock %} +{% block content %} + + +

Empréstimo Bancário

+{% endblock %} \ No newline at end of file diff --git a/expenses/templates/expenses/form/delete-expense.html b/expenses/templates/expenses/form/delete-expense.html new file mode 100644 index 00000000..fa36422d --- /dev/null +++ b/expenses/templates/expenses/form/delete-expense.html @@ -0,0 +1,92 @@ +
+ {% csrf_token %} + {{ form.as_p }} +
+ + +
+ +
+
+ \ No newline at end of file diff --git a/expenses/templates/expenses/form/edit-expense.html b/expenses/templates/expenses/form/edit-expense.html new file mode 100644 index 00000000..aaeb57e2 --- /dev/null +++ b/expenses/templates/expenses/form/edit-expense.html @@ -0,0 +1,97 @@ +
+ {% csrf_token %} + {{ form.as_p }} +
+ + +
+ +
+
+ \ No newline at end of file diff --git a/expenses/templates/expenses/form/handle-limit.html b/expenses/templates/expenses/form/handle-limit.html new file mode 100644 index 00000000..f763b3e7 --- /dev/null +++ b/expenses/templates/expenses/form/handle-limit.html @@ -0,0 +1,94 @@ +
+ {% csrf_token %} + {{ form.as_p }} +
+ + +
+ +
+
+ \ No newline at end of file diff --git a/expenses/templates/expenses/form/new-category.html b/expenses/templates/expenses/form/new-category.html new file mode 100644 index 00000000..ae9be59d --- /dev/null +++ b/expenses/templates/expenses/form/new-category.html @@ -0,0 +1,126 @@ +{% load static %} +{% block style %} + +{% endblock %} + +
+ {% csrf_token %} + {{ form.as_p }} + +
+
+

Alterar Categorias

+
+
+

Descrição

+

Excluir

+
+ {% for category in categories %} +
+

{{ category.description }}

+
+
+ +
+
+
+ {% endfor %} +
+ +
+ + +
+ +
+ + + +
+ \ No newline at end of file diff --git a/expenses/templates/expenses/form/new-payment.html b/expenses/templates/expenses/form/new-payment.html new file mode 100644 index 00000000..e10c2232 --- /dev/null +++ b/expenses/templates/expenses/form/new-payment.html @@ -0,0 +1,120 @@ +{% load static %} +{% block style %} + +{% endblock %} + +
+ {% csrf_token %} + {{ form.as_p }} + +
+
+

Alterar Forma de Pagamento

+
+
+

Descrição

+

Excluir

+
+ {% for payment in payments %} +
+

{{ payment.description }}

+
+
+ +
+
+
+ {% endfor %} +
+ +
+ + +
+ +
+ +
+ \ No newline at end of file diff --git a/expenses/templates/expenses/list-expenses-by-category.html b/expenses/templates/expenses/list-expenses-by-category.html index 6543199a..65286392 100644 --- a/expenses/templates/expenses/list-expenses-by-category.html +++ b/expenses/templates/expenses/list-expenses-by-category.html @@ -1,24 +1,46 @@ +{% extends "base.html" %} +{% load static %} +{% block title %}Relatório de Gastos Mensais por Categoria{% endblock %} +{% block style %} + -
- {% csrf_token %} - {{ form.as_p }} - -
+ +{% endblock %} +{% block content %} +
Todos os Relatórios/Relatório de Gastos Mensais por Categoria
+
+
+ {% csrf_token %} + {{ form.as_p }} + +
+ + -
-

{{ category_selected }}

-{% if list %} - - - - - - - {% for result in list %} - - - - - - {% endfor %} -{% endif %} + {% if list %} + +
+
+

Categoria: {{ category_selected }}

+
+
+

+

Mês

+

Ano

+

Total

+

+
+ {% for result in list %} +
+

+

{{ result.date__month }}

+

{{ result.date__year }}

+

{{ result.total|floatformat:2 }}

+

+
+ {% endfor %} +
+ + {% endif %} + + {% endblock %} \ No newline at end of file diff --git a/expenses/templates/expenses/main.html b/expenses/templates/expenses/main.html index f1104169..b2be7840 100644 --- a/expenses/templates/expenses/main.html +++ b/expenses/templates/expenses/main.html @@ -28,7 +28,7 @@

Inserir ou Alterar

-
+
@@ -41,6 +41,12 @@
+
@@ -63,10 +69,10 @@

{{ item.payment.description|title }}

R$ {{ item.value|floatformat:2 }}

-
+
-
+
@@ -135,14 +141,43 @@ 'handle-limit': "{% url 'expenses:handle_limit' %}", 'handle-payment': "{% url 'expenses:handle_payment' %}", 'handle-category': "{% url 'expenses:handle_category' %}", + 'edit-expense': "{% url 'expenses:edit_expense' %}", + 'delete-expense': "{% url 'expenses:delete_expense' %}", } $(".action-modal").on('click', function(){ //console.log($(this).data().action) + new_data = {} + if($(this).data().action == 'edit-expense'){ + new_data = { + category: $('#category :selected').val(), + payment: $('#payment :selected').val(), + description: $('#description :selected').val(), + value: $('#value :selected').val(), + date: $('#date :selected').val(), + } + } + if($(this).data().action == 'edit-category'){ + new_data = { + id: $(this).data().id, + } + } + if($(this).data().id){ + new_data = { + id: $(this).data().id, + } + } + + if($(this).data().action == 'handle-limit'){ + new_data = { + month_year: $('#list_month_year :selected').val(), + } + } $.ajax({ type: 'GET', url: action_modal[$(this).data().action], + data: new_data, success: function (response) { $('.modal-description').text(response.title); $('.modal-content').html(response.html); diff --git a/expenses/templates/expenses/report.html b/expenses/templates/expenses/report.html index c7c295ac..62c215f2 100644 --- a/expenses/templates/expenses/report.html +++ b/expenses/templates/expenses/report.html @@ -2,5 +2,11 @@ {% load static %} {% block title %}Relatórios{% endblock %} {% block content %} - Contéudo de relatório... + + +

Todos os Relatórios

+ + {% endblock %} \ No newline at end of file diff --git a/expenses/urls.py b/expenses/urls.py index ac4e30dd..cc0a86a0 100644 --- a/expenses/urls.py +++ b/expenses/urls.py @@ -10,6 +10,7 @@ path('get/report/list-expenses-by-category/', list_expenses_by_category, name="list_expenses_by_category"), path('report/', report, name="report"), path('about/', about, name="about"), + path('bank-loan/', bank_loan, name="bank_loan"), path('get-total-expenses/',get_total_expenses_ajax,name="get_total_expenses_ajax"), @@ -19,6 +20,8 @@ path('handle/limit', handle_limit, name="handle_limit"), path('handle/payment', handle_payment, name="handle_payment"), path('handle/category', handle_category, name="handle_category"), + path('edit/expense', edit_expense, name="edit_expense"), + path('delete/expense', delete_expense, name="delete_expense") ] \ No newline at end of file diff --git a/expenses/views.py b/expenses/views.py index 4426f7ac..f5b55079 100644 --- a/expenses/views.py +++ b/expenses/views.py @@ -1,3 +1,5 @@ +from multiprocessing import context +from unicodedata import category from django.shortcuts import render,redirect from django.urls import reverse @@ -86,11 +88,6 @@ def home(request,page=None): # list_item_expenses = Expense.objects.all()[:NUMBER_ITENS] # else: # list_item_expenses = Expense.objects.all() - - - - - context = { 'page_selected': "home", @@ -119,6 +116,12 @@ def report(request): } return render(request,"expenses/report.html", context) +def bank_loan(request): + context = { + 'page_selected': "bank-loan", + } + return render(request,"expenses/bank-loan.html", context) + def list_expenses_by_category(request): @@ -130,12 +133,14 @@ def list_expenses_by_category(request): context = { 'form': form, 'category_selected': category, - 'list':list + 'list':list, + 'page_selected': "report", } return render(request,'expenses/list-expenses-by-category.html',context) form = SelectCategoryForm() context = { 'form': form, + 'page_selected': "report", } return render(request,'expenses/list-expenses-by-category.html',context) @@ -160,7 +165,9 @@ def get_total_expenses_ajax(request): from expenses.forms import ExpenseForm from django.template.loader import render_to_string +from django.views.decorators.csrf import csrf_exempt +@csrf_exempt def create_expense(request): title = 'Inserir Gasto' context_extra = {} @@ -194,31 +201,164 @@ def create_expense(request): } return JsonResponse(response, status = 200) +from expenses.forms import CategoryForm +@csrf_exempt def handle_category(request): - title = 'Inserir Categoria' + title = "Inserir Categoria" + context_extra = {} + if request.POST.get('action') == 'post': + form = CategoryForm(request.POST) + + if form.is_valid(): + model = form.save(commit=False) + model.save() + context_extra = { + 'response' : 'Criado com sucesso!', + 'error': False, + } + else: + context_extra = { + 'response' : 'Erros ocorreram!', + 'error': True + } + + else: + form = CategoryForm() + context = { + 'form': form, + 'categories': Category.objects.all() + } + html_page = render_to_string('expenses/form/new-category.html', context) response = { 'title' : title, - 'html' : 'a fazer...', - + 'html' : html_page, + 'response' : context_extra['response'] if 'response' in context_extra else None, + 'error': context_extra['error'] if 'error' in context_extra else None, } return JsonResponse(response, status = 200) - +from expenses.forms import LimitForm +from expenses.models import Limit +@csrf_exempt def handle_limit(request): title = 'Inserir Limite' + context_extra = {} + if request.POST.get('action') == 'post': + + month, year = request.POST['month'], request.POST['year'] + + if Limit.objects.filter(month=month,year=year).exists(): + instance = Limit.objects.get(month=month,year=year) + form = LimitForm(request.POST,instance=instance) + else: + form = LimitForm(request.POST) + + if form.is_valid(): + model = form.save(commit=False) + model.save() + context_extra = { + 'response' : 'Criado com sucesso!', + 'error': False, + } + else: + context_extra = { + 'response' : 'Erros ocorreram!', + 'error': True + } + + else: + value = request.GET['month_year'] + value = value.split('-') + month, year = value[0], value[1] + total = 0 + if Limit.objects.filter(month=month,year=year).exists(): + total = Limit.objects.get(month=month,year=year).value + form = LimitForm(initial={'month': month, 'year': year, 'value': total}) + context = { + 'form': form, + } + html_page = render_to_string('expenses/form/handle-limit.html', context) response = { 'title' : title, - 'html' : 'a fazer...', - + 'html' : html_page, + 'response' : context_extra['response'] if 'response' in context_extra else None, + 'error': context_extra['error'] if 'error' in context_extra else None, } return JsonResponse(response, status = 200) +from expenses.forms import PaymentForm +@csrf_exempt + def handle_payment(request): - title = 'Inserir Forma de Pagamento' + title = 'Inserir Pagamento' + context_extra = {} + if request.POST.get('action') == 'post': + form = PaymentForm(request.POST) + + if form.is_valid(): + model = form.save(commit=False) + model.save() + context_extra = { + 'response' : 'Criado com sucesso!', + 'error': False, + } + else: + context_extra = { + 'response' : 'Erros ocorreram!', + 'error': True + } + + else: + form = PaymentForm() + context = { + 'form': form, + 'payments': Payment.objects.all(), + } + html_page = render_to_string('expenses/form/new-payment.html', context) + response = { + 'title' : title, + 'html' : html_page, + 'response' : context_extra['response'] if 'response' in context_extra else None, + 'error': context_extra['error'] if 'error' in context_extra else None, + } + return JsonResponse(response, status = 200) + +from expenses.forms import EditExpenseForm +@csrf_exempt + +def edit_expense(request): + title = 'Alterar Gasto' + expense = Expense.objects.get(id=request.GET['id']) + context = { + 'expense': expense, + } + html_page = render_to_string('expenses/form/edit-expense.html', context) response = { 'title' : title, - 'html' : 'a fazer...', + 'html' : html_page, } + return JsonResponse(response, status = 200) + +def delete_expense(request): + title = 'Confirme para deletar:' + context_extra = {} + context = { + 'id': request.GET.get('id') + } + if request.GET.get('action') == 'delete': + id = request.GET.get('id') + Expense.objects.filter(id=id).delete() + context_extra = { + 'response' : 'Deletado com sucesso!', + 'error': False, + } + html_page = render_to_string('expenses/form/delete-expense.html', context) + response = { + 'title' : title, + 'html' : html_page, + 'response' : context_extra['response'] if 'response' in context_extra else None, + 'error': context_extra['error'] if 'error' in context_extra else None, + } return JsonResponse(response, status = 200) \ No newline at end of file
MêsAnoTotal
{{ result.date__month }}{{ result.date__year }}{{ result.total|floatformat:2 }}