From 50fe80969b9ddbfa795b11e303430d58a8e10a8c Mon Sep 17 00:00:00 2001
From: luxagraf
Date: Mon, 16 Mar 2015 22:31:32 -0400
Subject: added expense tracking app
---
app/expenses/__init__.py | 0
app/expenses/admin.py | 10 ++
app/expenses/models.py | 31 +++++
app/expenses/urls.py | 7 ++
app/expenses/views.py | 12 ++
app/lib/templatetags/templatetags/expense_total.py | 25 ++++
config/base_urls.py | 1 +
design/sass/_projects.scss | 49 ++++++++
design/templates/base.html | 1 +
design/templates/details/expenses.html | 132 +++++++++++++++++++++
10 files changed, 268 insertions(+)
create mode 100644 app/expenses/__init__.py
create mode 100644 app/expenses/admin.py
create mode 100644 app/expenses/models.py
create mode 100644 app/expenses/urls.py
create mode 100644 app/expenses/views.py
create mode 100644 app/lib/templatetags/templatetags/expense_total.py
create mode 100644 design/templates/details/expenses.html
diff --git a/app/expenses/__init__.py b/app/expenses/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/app/expenses/admin.py b/app/expenses/admin.py
new file mode 100644
index 0000000..f014dca
--- /dev/null
+++ b/app/expenses/admin.py
@@ -0,0 +1,10 @@
+from django.contrib import admin
+
+from .models import Expense
+
+
+class ExpenseAdmin(admin.ModelAdmin):
+ list_display = ('name', 'category', 'amount', 'date_month')
+
+
+admin.site.register(Expense, ExpenseAdmin)
diff --git a/app/expenses/models.py b/app/expenses/models.py
new file mode 100644
index 0000000..a01b8d7
--- /dev/null
+++ b/app/expenses/models.py
@@ -0,0 +1,31 @@
+from django.db import models
+from django.template.defaultfilters import slugify
+import datetime
+
+CATS = (
+ ('1', "Yellowstone"),
+ ('2', "Suburban"),
+ ('3', "Groceries"),
+ ('4', "Lodging"),
+ ('5', "Camping"),
+ ('6', "Restaurants"),
+ ('7', "Petrol"),
+ ('8', "Misc"),
+)
+
+class Expense(models.Model):
+ name = models.CharField(max_length=200)
+ amount = models.DecimalField(max_digits=8, decimal_places=2)
+ date = models.DateTimeField(default=datetime.date.today())
+ notes = models.TextField(null=True, blank=True)
+ category = models.CharField(max_length=2, choices=CATS, default=1)
+
+ class Meta:
+ ordering = ('-date',)
+
+ def __str__(self):
+ return self.name
+
+ def date_month(self):
+ return self.date.strftime("%b %Y")
+
diff --git a/app/expenses/urls.py b/app/expenses/urls.py
new file mode 100644
index 0000000..ae7cad6
--- /dev/null
+++ b/app/expenses/urls.py
@@ -0,0 +1,7 @@
+from django.conf.urls import *
+from django.views.generic.base import RedirectView
+
+
+urlpatterns = patterns('',
+ url(r'yellowstone-suburban-trip-costs/', 'expenses.views.detail'),
+)
diff --git a/app/expenses/views.py b/app/expenses/views.py
new file mode 100644
index 0000000..7442178
--- /dev/null
+++ b/app/expenses/views.py
@@ -0,0 +1,12 @@
+from django.shortcuts import render_to_response, get_object_or_404
+from django.template import RequestContext
+
+from .models import Expense, CATS
+
+def detail(request):
+ context = {
+ 'object_list': Expense.objects.all(),
+ 'categories': CATS
+ }
+ return render_to_response('details/expenses.html', context, context_instance=RequestContext(request))
+
diff --git a/app/lib/templatetags/templatetags/expense_total.py b/app/lib/templatetags/templatetags/expense_total.py
new file mode 100644
index 0000000..8bf0953
--- /dev/null
+++ b/app/lib/templatetags/templatetags/expense_total.py
@@ -0,0 +1,25 @@
+from decimal import Decimal
+from django import template
+from django.utils.safestring import mark_safe
+register = template.Library()
+
+@register.filter
+def expense_total(values):
+ """
+ converts spaces to hyphens.
+ """
+ total = 0
+ for items in values:
+ for item in items['list']:
+ total += Decimal(item.amount)
+ return mark_safe(total)
+
+@register.filter
+def cat_total(values):
+ """
+ converts spaces to hyphens.
+ """
+ total = 0
+ for val in values:
+ total += Decimal(val.amount)
+ return mark_safe(total)
diff --git a/config/base_urls.py b/config/base_urls.py
index 56612ff..c606171 100644
--- a/config/base_urls.py
+++ b/config/base_urls.py
@@ -52,6 +52,7 @@ urlpatterns += patterns('',
#old: (r'(?P\d{4})/(?P[a-z]{3})/(?P\w{1,2})/(?P[-\w]+)/$', 'blog.views.entry_detail'),
# locations
(r'^locations/', include('locations.urls')),
+ (r'^expenses/', include('expenses.urls')),
(r'^photos/', include('photos.urls')),
(r'^field-notes/', include('notes.urls')),
(r'^photo/', include('photos.detail_urls')),
diff --git a/design/sass/_projects.scss b/design/sass/_projects.scss
index fb3f530..e7cdf09 100644
--- a/design/sass/_projects.scss
+++ b/design/sass/_projects.scss
@@ -204,3 +204,52 @@
}
}
}
+
+//################# EXPENSE TRACKER TABLES #######################
+
+.expense-wrapper {
+ @include constrain_narrow();
+}
+.expense {
+ min-width: 90%;
+ margin-bottom: 3em;
+ caption {
+ text-align: left;
+ padding: 1em 0;
+ @include fontsize(18);
+ }
+ thead tr {
+ border-bottom: 1px solid darken(#eff7ff, 10);
+ padding: 0;
+ font-weight: bold;
+ @include smcaps;
+ font-family: sans-serif;
+ @include fontsize(12);
+ }
+ text-align: left;
+ td {
+ width: 80%;
+ }
+ tr td {
+ padding: .5em .25em;
+ color: lighten($body_font, 10);
+ }
+ .odd, .total {
+ background-color: #eff7ff;
+ }
+ .total {
+ border-top: 1px solid darken(#eff7ff, 10);
+ }
+ tfoot:after {
+ @include faded_line_after;
+ }
+}
+
+.end:after {
+ @include faded_line_after;
+}
+.upfront tfoot:after {
+ margin: 0;
+ height: 0;
+ background: none;
+ }
diff --git a/design/templates/base.html b/design/templates/base.html
index 4fba739..4a8a182 100644
--- a/design/templates/base.html
+++ b/design/templates/base.html
@@ -60,6 +60,7 @@
Scott Gilbertson, except photos, which are licensed under the Creative Commons (details).
+
{% block js %}{% endblock%}