diff --git a/website/miniconcrexit/templates/base.html b/website/miniconcrexit/templates/base.html index 04ddf05..328534e 100644 --- a/website/miniconcrexit/templates/base.html +++ b/website/miniconcrexit/templates/base.html @@ -20,6 +20,10 @@ Home + {% if user.is_authenticated %} + Reimbursements + {% endif %} + {% if user.is_staff %} Admin {% endif %} diff --git a/website/reimbursements/admin.py b/website/reimbursements/admin.py index fe90052..92b955f 100644 --- a/website/reimbursements/admin.py +++ b/website/reimbursements/admin.py @@ -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 diff --git a/website/reimbursements/migrations/0001_initial.py b/website/reimbursements/migrations/0001_initial.py new file mode 100644 index 0000000..37ad045 --- /dev/null +++ b/website/reimbursements/migrations/0001_initial.py @@ -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"], + }, + ), + ] diff --git a/website/reimbursements/models.py b/website/reimbursements/models.py index ffd95ee..68fe51a 100644 --- a/website/reimbursements/models.py +++ b/website/reimbursements/models.py @@ -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}" diff --git a/website/reimbursements/templates/reimbursements/create.html b/website/reimbursements/templates/reimbursements/create.html new file mode 100644 index 0000000..abdbbea --- /dev/null +++ b/website/reimbursements/templates/reimbursements/create.html @@ -0,0 +1,10 @@ +{% extends 'base.html' %} +{% load django_bootstrap5 %} +{% block body %} +
+ 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. +
+ Submit new reimbursement + + {% if object_list %} +# | +Created | +Date incurred | +Description | +Amount | +Approved | +
---|---|---|---|---|---|
{{ object.id }} | +{{ object.created }} | +{{ object.date_incurred }} | +{{ object.description }} | +€ {{ object.amount }} | +{% if object.approved %}{{ object.approved_at }}{% else %}Pending{% endif %} | +