-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
226 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,40 @@ | ||
# Create an admin interface for your model here. | ||
from django.contrib import admin | ||
from django.contrib.admin import register | ||
from django.utils import timezone | ||
from reimbursements import models | ||
|
||
|
||
@register(models.Reimbursement) | ||
class ReimbursementAdmin(admin.ModelAdmin): | ||
list_display = ( | ||
"id", | ||
"created", | ||
"owner", | ||
"date_incurred", | ||
"amount", | ||
"approved", | ||
) | ||
list_filter = ("approved", "created", "date_incurred", "owner") | ||
|
||
autocomplete_fields = ["owner"] | ||
readonly_fields = ["approved_by", "approved_at", "created", "updated"] | ||
|
||
def save_model(self, request, obj, form, change): | ||
if obj.approved and not form.initial["approved"]: | ||
obj.approved = True | ||
obj.approved_by = request.user | ||
obj.approved_at = timezone.now() | ||
|
||
super().save_model(request, obj, form, change) | ||
|
||
def get_readonly_fields(self, request, obj=None): | ||
if obj and obj.approved: | ||
return self.readonly_fields + [ | ||
"approved", | ||
"amount", | ||
"description", | ||
"receipt", | ||
"date_incurred", | ||
"owner", | ||
] | ||
return self.readonly_fields |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
# Generated by Django 4.2.5 on 2023-09-09 20:11 | ||
|
||
import django.db.models.deletion | ||
from django.conf import settings | ||
from django.db import migrations, models | ||
|
||
|
||
class Migration(migrations.Migration): | ||
initial = True | ||
|
||
dependencies = [ | ||
migrations.swappable_dependency(settings.AUTH_USER_MODEL), | ||
] | ||
|
||
operations = [ | ||
migrations.CreateModel( | ||
name="Reimbursement", | ||
fields=[ | ||
( | ||
"id", | ||
models.BigAutoField( | ||
auto_created=True, | ||
primary_key=True, | ||
serialize=False, | ||
verbose_name="ID", | ||
), | ||
), | ||
("amount", models.DecimalField(decimal_places=2, max_digits=10)), | ||
("date_incurred", models.DateField()), | ||
("description", models.TextField()), | ||
("receipt", models.FileField(upload_to="receipts/")), | ||
("created", models.DateTimeField(auto_now_add=True)), | ||
("updated", models.DateTimeField(auto_now=True)), | ||
("approved", models.BooleanField(default=False)), | ||
("approved_at", models.DateTimeField(null=True)), | ||
( | ||
"approved_by", | ||
models.ForeignKey( | ||
editable=False, | ||
null=True, | ||
on_delete=django.db.models.deletion.SET_NULL, | ||
related_name="reimbursements_approved", | ||
to=settings.AUTH_USER_MODEL, | ||
), | ||
), | ||
( | ||
"owner", | ||
models.ForeignKey( | ||
null=True, | ||
on_delete=django.db.models.deletion.SET_NULL, | ||
related_name="reimbursements", | ||
to=settings.AUTH_USER_MODEL, | ||
), | ||
), | ||
], | ||
options={ | ||
"ordering": ["created"], | ||
}, | ||
), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,35 @@ | ||
# Create a model here. | ||
from django.db import models | ||
|
||
|
||
class Reimbursement(models.Model): | ||
owner = models.ForeignKey( | ||
"auth.User", | ||
related_name="reimbursements", | ||
on_delete=models.SET_NULL, | ||
null=True, | ||
blank=False, | ||
) | ||
|
||
amount = models.DecimalField(max_digits=10, decimal_places=2) | ||
date_incurred = models.DateField() | ||
description = models.TextField() | ||
receipt = models.FileField(upload_to="receipts/") | ||
|
||
created = models.DateTimeField(auto_now_add=True) | ||
updated = models.DateTimeField(auto_now=True) | ||
|
||
approved = models.BooleanField(default=False) | ||
approved_at = models.DateTimeField(null=True) | ||
approved_by = models.ForeignKey( | ||
"auth.User", | ||
related_name="reimbursements_approved", | ||
on_delete=models.SET_NULL, | ||
editable=False, | ||
null=True, | ||
) | ||
|
||
class Meta: | ||
ordering = ["created"] | ||
|
||
def __str__(self): | ||
return f"Reimbursement #{self.id}" |
10 changes: 10 additions & 0 deletions
10
website/reimbursements/templates/reimbursements/create.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{% extends 'base.html' %} | ||
{% load django_bootstrap5 %} | ||
{% block body %} | ||
<h1>Request reimbursement</h1> | ||
<form method="post" class="form" enctype="multipart/form-data"> | ||
{% csrf_token %} | ||
{% bootstrap_form form %} | ||
{% bootstrap_button button_type="submit" content="Submit" %} | ||
</form> | ||
{% endblock %} |
41 changes: 41 additions & 0 deletions
41
website/reimbursements/templates/reimbursements/index.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
{% extends 'base.html' %} | ||
{% block body %} | ||
<h1>My reimbursements</h1> | ||
<p> | ||
If you have made costs for Thalia, you can submit them here to request reimbursement. | ||
Please note that you can only submit costs for which you have a receipt. | ||
If you have any questions, please contact the treasurer. | ||
</p> | ||
<a href="{% url 'reimbursements:create' %}" class="btn btn-primary mb-3">Submit new reimbursement</a> | ||
|
||
{% if object_list %} | ||
<table class="table"> | ||
<thead> | ||
<tr> | ||
<th scope="col">#</th> | ||
<th scope="col">Created</th> | ||
<th scope="col">Date incurred</th> | ||
<th scope="col">Description</th> | ||
<th scope="col">Amount</th> | ||
<th scope="col">Approved</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{% for object in object_list %} | ||
<tr> | ||
<th scope="row">{{ object.id }}</th> | ||
<td>{{ object.created }}</td> | ||
<td>{{ object.date_incurred }}</td> | ||
<td>{{ object.description }}</td> | ||
<td>€ {{ object.amount }}</td> | ||
<td>{% if object.approved %}{{ object.approved_at }}{% else %}Pending{% endif %}</td> | ||
</tr> | ||
{% endfor %} | ||
</tbody> | ||
</table> | ||
{% else %} | ||
<div class="alert alert-info" role="alert"> | ||
<span>You have not submitted any reimbursements yet.</span> | ||
</div> | ||
{% endif %} | ||
{% endblock %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,9 @@ | ||
from django.urls import path | ||
from reimbursements.views import CreateReimbursementView, IndexView | ||
|
||
app_name = "reimbursements" | ||
|
||
urlpatterns = [] | ||
urlpatterns = [ | ||
path("", IndexView.as_view(), name="index"), | ||
path("create/", CreateReimbursementView.as_view(), name="create"), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,31 @@ | ||
# Write your views here. Create templates in `reimbursements/templates/reimbursements/`. | ||
from django.contrib.auth.mixins import LoginRequiredMixin | ||
from django.urls import reverse_lazy | ||
from django.views.generic import CreateView, ListView | ||
from reimbursements.models import Reimbursement | ||
|
||
|
||
class IndexView(LoginRequiredMixin, ListView): | ||
model = Reimbursement | ||
template_name = "reimbursements/index.html" | ||
|
||
def get_queryset(self): | ||
return super().get_queryset().filter(owner=self.request.user) | ||
|
||
|
||
class CreateReimbursementView(CreateView): | ||
model = Reimbursement | ||
template_name = "reimbursements/create.html" | ||
|
||
fields = ["date_incurred", "amount", "description", "receipt"] | ||
|
||
success_url = reverse_lazy("reimbursements:index") | ||
|
||
def form_valid(self, form): | ||
form.instance.owner = self.request.user | ||
form.save() | ||
return super().form_valid(form) | ||
|
||
def get_context_data(self, **kwargs): | ||
context = super().get_context_data() | ||
context["form"].fields["date_incurred"].widget.input_type = "date" | ||
return context |