summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/budget/migrations/0002_alter_luxpurchase_amount.py18
-rw-r--r--app/budget/migrations/0003_alter_luxpurchase_category_alter_luxpurchase_source.py23
-rw-r--r--app/budget/migrations/0004_alter_luxpurchase_source.py19
-rw-r--r--app/budget/models.py36
-rw-r--r--app/budget/templates/budget/base.html2
-rw-r--r--app/budget/templates/budget/luxpurchase_list.html46
-rw-r--r--app/budget/templates/budget/update_form.html20
-rw-r--r--app/budget/urls.py2
-rw-r--r--app/budget/views.py34
9 files changed, 194 insertions, 6 deletions
diff --git a/app/budget/migrations/0002_alter_luxpurchase_amount.py b/app/budget/migrations/0002_alter_luxpurchase_amount.py
new file mode 100644
index 0000000..06400dd
--- /dev/null
+++ b/app/budget/migrations/0002_alter_luxpurchase_amount.py
@@ -0,0 +1,18 @@
+# Generated by Django 4.0.6 on 2022-11-11 18:06
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('budget', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='luxpurchase',
+ name='amount',
+ field=models.DecimalField(decimal_places=2, max_digits=6),
+ ),
+ ]
diff --git a/app/budget/migrations/0003_alter_luxpurchase_category_alter_luxpurchase_source.py b/app/budget/migrations/0003_alter_luxpurchase_category_alter_luxpurchase_source.py
new file mode 100644
index 0000000..a880acf
--- /dev/null
+++ b/app/budget/migrations/0003_alter_luxpurchase_category_alter_luxpurchase_source.py
@@ -0,0 +1,23 @@
+# Generated by Django 4.0.6 on 2022-11-12 10:18
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('budget', '0002_alter_luxpurchase_amount'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='luxpurchase',
+ name='category',
+ field=models.IntegerField(choices=[(0, 'Grocery & Home'), (1, 'Gas'), (2, 'Bus'), (3, 'Lodging'), (4, 'Books'), (5, 'Clothes'), (6, 'Eating Out'), (7, 'Misc')], default=0),
+ ),
+ migrations.AlterField(
+ model_name='luxpurchase',
+ name='source',
+ field=models.IntegerField(choices=[(0, 'Walmart'), (1, 'Grocery Store'), (2, 'Gas Station'), (3, 'Amazon')], default=0),
+ ),
+ ]
diff --git a/app/budget/migrations/0004_alter_luxpurchase_source.py b/app/budget/migrations/0004_alter_luxpurchase_source.py
new file mode 100644
index 0000000..0eab270
--- /dev/null
+++ b/app/budget/migrations/0004_alter_luxpurchase_source.py
@@ -0,0 +1,19 @@
+# Generated by Django 4.0.6 on 2022-11-12 10:46
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('budget', '0003_alter_luxpurchase_category_alter_luxpurchase_source'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='luxpurchase',
+ name='source',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='budget.luxsource'),
+ ),
+ ]
diff --git a/app/budget/models.py b/app/budget/models.py
index acf2b69..f4c6ec0 100644
--- a/app/budget/models.py
+++ b/app/budget/models.py
@@ -1,4 +1,10 @@
+import calendar
+import datetime
from django.db import models
+from django.db.models import Sum
+from django.urls import reverse
+from django.utils import timezone
+
class LuxSource(models.Model):
name = models.CharField(max_length=200)
@@ -7,11 +13,29 @@ class LuxSource(models.Model):
def __str__(self):
return self.name
+
+class LuxPurchaseStatsManager(models.Manager):
+
+ def get_monthly_spending(self, month=timezone.now().month):
+ last_day = calendar.monthrange(timezone.now().year, month)[1]
+ start_date = datetime.date(timezone.now().year, month, 1)
+ end_date = datetime.date(timezone.now().year, month, last_day)
+ return self.filter(date_recorded__range=(start_date, end_date)).aggregate(Sum('amount'))
+
+ def get_monthly_spending_by_category(self, cat, number_of_months=1):
+ today = timezone.now()
+ month = today.replace(day=1).month
+ start_month = month - number_of_months + 1
+ start_date = datetime.date(timezone.now().year, start_month, 1)
+ last_day = calendar.monthrange(timezone.now().year, month)[1]
+ end_date = datetime.date(timezone.now().year, month, last_day)
+ return self.filter(date_recorded__range=(start_date, end_date)).filter(category=cat).aggregate(Sum('amount'))
+
class LuxPurchase(models.Model):
- amount = models.IntegerField()
+ amount = models.DecimalField(max_digits=6, decimal_places=2)
source = models.ForeignKey(LuxSource, on_delete=models.CASCADE)
CATEGORY = (
- (0, 'Grocery and Home'),
+ (0, 'Grocery & Home'),
(1, 'Gas'),
(2, 'Bus'),
(3, 'Lodging'),
@@ -27,5 +51,11 @@ class LuxPurchase(models.Model):
ordering = ('-date_recorded',)
def __str__(self):
- return self.name
+ return "%s - %s" %(self.amount, self.source.name)
+
+ def get_absolute_url(self):
+ return reverse("luxbudget:detail", kwargs={"pk": self.pk})
+
+ objects = models.Manager() # The default manager.
+ stats = LuxPurchaseStatsManager()
diff --git a/app/budget/templates/budget/base.html b/app/budget/templates/budget/base.html
index e17813a..355c911 100644
--- a/app/budget/templates/budget/base.html
+++ b/app/budget/templates/budget/base.html
@@ -23,7 +23,7 @@
</head>
<body>
<nav>
- <span class="nav-item"><a href="{% url 'luxtrade:list' %}">Home</a></span>
+ <span class="nav-item"><a href="{% url 'luxbudget:list' %}">Home</a></span>
</nav>
{% block content %}
{% endblock %}
diff --git a/app/budget/templates/budget/luxpurchase_list.html b/app/budget/templates/budget/luxpurchase_list.html
new file mode 100644
index 0000000..765834a
--- /dev/null
+++ b/app/budget/templates/budget/luxpurchase_list.html
@@ -0,0 +1,46 @@
+{% extends 'budget/base.html' %}
+{% load typogrify_tags %}
+ {% block pagetitle %}Luxagraf - Record Purchase{% endblock %}
+ {% block content %}
+ <a href="record" class="btn" >Add New</a>
+ <h3>Recent Purchases</h3>
+ <table>
+ <thead>
+ <tr>
+ <th>Date</th>
+ <th>Store</th>
+ <th>Category</th>
+ <th>Amount</th>
+ </tr>
+ </thead>
+ {% for object in object_list %}
+ <tr>
+ <td><a href="{{object.get_absolute_url}}">{{object.date_recorded|date:"m/j"}}</a></td>
+ <td>{{object.source.name}}</td>
+ <td>{{object.get_category_display}}</td>
+ <td>${{object.amount}}</td>
+ </tr>
+ {% endfor %}
+ <tr>
+ <td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="right">{{month}} Total:</td>
+ <td>${{monthly_spending.amount__sum}}</td>
+ </tr>
+ </table>
+
+ <h3>Previous Monthly Spending</h3>
+ {{month_1}}: {{monthly_spending_1.amount__sum}}
+ {{month_2}}: {{monthly_spending_2.amount__sum}}
+ {{month_3}}: {{monthly_spending_3.amount__sum}}
+
+
+ <h3>Spending by Category (Last 3 Months)</h3>
+
+ {{cat.amount__sum}}
+ {% endblock %}
+
+
diff --git a/app/budget/templates/budget/update_form.html b/app/budget/templates/budget/update_form.html
new file mode 100644
index 0000000..b19efaa
--- /dev/null
+++ b/app/budget/templates/budget/update_form.html
@@ -0,0 +1,20 @@
+{% extends 'budget/base.html' %}
+{% load typogrify_tags %}
+{% block content %}
+ <form id="id_form" action="" method="post" class="big">{% csrf_token %}
+ {% for field in form %}
+ <fieldset>
+ {{ field.errors }}
+ {% if field.name == 'status'%}
+ <label class="hide" for="id_status">Status:</label>{{ field }}
+ {% else %}
+ {{ field.label_tag }} {{ field }}
+ {% endif %}
+ {% if field.help_text %}
+ <p class="help">{{ field.help_text|safe }}</p>
+ {% endif %}
+ </fieldset>
+{% endfor %}
+ <input type="submit" name="post" class="btn" value="update purchase"/>
+ </form>
+ {% endblock %}
diff --git a/app/budget/urls.py b/app/budget/urls.py
index 86c56a2..92fc184 100644
--- a/app/budget/urls.py
+++ b/app/budget/urls.py
@@ -12,7 +12,7 @@ urlpatterns = [
),
path(
'purchase/<pk>',
- views.PurchaseModelFormView.as_view(),
+ views.PurchaseUpdateView.as_view(),
name='detail'
),
path(
diff --git a/app/budget/views.py b/app/budget/views.py
index 3743eaf..e291bde 100644
--- a/app/budget/views.py
+++ b/app/budget/views.py
@@ -1,5 +1,7 @@
+import datetime
from django.shortcuts import render
from django.views.generic.edit import CreateView, UpdateView
+from django.utils import timezone
from utils.views import PaginatedListView
from .models import LuxPurchase
@@ -9,5 +11,35 @@ class PurchaseModelFormView(CreateView):
success_url = '/spending/'
template_name = 'budget/create_form.html'
+
+class PurchaseUpdateView(UpdateView):
+ model = LuxPurchase
+ fields = ['amount', 'source', 'category']
+ success_url = '/spending/'
+ template_name = 'budget/update_form.html'
+
+
class LuxPurchaseListView(PaginatedListView):
- pass
+ model = LuxPurchase
+
+ def get_context_data(self, **kwargs):
+ '''
+ Get Monthly Spending for a nice bar chart
+ '''
+ # Call the base implementation first to get a context
+ context = super(LuxPurchaseListView, self).get_context_data(**kwargs)
+ context['monthly_spending'] = LuxPurchase.stats.get_monthly_spending()
+ today = timezone.now()
+ first = today.replace(day=1)
+ month_1 = first - datetime.timedelta(days=1)
+ month_2 = month_1.replace(day=1) - datetime.timedelta(days=1)
+ month_3 = month_2.replace(day=1) - datetime.timedelta(days=1)
+ context['month'] = today.strftime('%h')
+ context['monthly_spending_1'] = LuxPurchase.stats.get_monthly_spending(month_1.month)
+ context['month_1'] = month_1.strftime('%h')
+ context['monthly_spending_2'] = LuxPurchase.stats.get_monthly_spending(month_2.month)
+ context['month_2'] = month_2.strftime('%h')
+ context['monthly_spending_3'] = LuxPurchase.stats.get_monthly_spending(month_3.month)
+ context['month_3'] = month_3.strftime('%h')
+ context['cat'] = LuxPurchase.stats.get_monthly_spending_by_category(1, 3)
+ return context