Home

mint @e9a605f47f57723424ae99e169737262e9b0d31d - refs - log -
-
https://git.jolheiser.com/mint.git
Budget
mint / budget / views.py
- raw -
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
from django.shortcuts import render
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views import View
from django.http import HttpRequest, JsonResponse, HttpResponse
from datetime import date, datetime, timedelta
from .models import Transaction, Recurrence
import json

from .utils import prev_month_range, add_months

BLUE = "#3788d8"
YELLOW = "#d4a574"
GREEN = "#a8d5ba"
WHITE = "#fff"
BLACK = "#000"
GRAY = "#6a7282"


class IndexView(LoginRequiredMixin, View):
    def get(self, request: HttpRequest) -> HttpResponse:
        return render(request, "budget/index.html")


class EventsView(LoginRequiredMixin, View):
    def get(self, request: HttpRequest) -> JsonResponse:
        data = request.GET
        # 2025-07-27T00:00:00-05:00
        start = datetime.fromisoformat(data["start"]) if "start" in data else date.min
        end = datetime.fromisoformat(data["end"]) if "end" in data else date.max
        transactions = Transaction.objects.filter(date__range=[start, end])
        events = []
        today = datetime.now().date()
        for t in transactions:
            bg, border, text = BLUE, BLUE, WHITE
            if t.is_income:
                bg, border, text = GREEN, GREEN, BLACK
            if t.recurrence == "":
                border = YELLOW
            if t.date < today:
                bg, border, text = GRAY, GREEN if t.is_income else BLUE, WHITE
            events.append(
                {
                    "id": t.id,
                    "allDay": True,
                    "start": t.date,
                    "title": t.display,
                    "extendedProps": {
                        "title": t.title,
                        "amount": t.cents,
                        "recurrence": t.recurrence,
                        "week": t.week,
                        "income": t.is_income,
                    },
                    "backgroundColor": bg,
                    "borderColor": border,
                    "textColor": text,
                }
            )
        return JsonResponse(events, safe=False)


class TransactionView(LoginRequiredMixin, View):

    def post(self, request: HttpRequest) -> HttpResponse:
        data = json.loads(request.body)
        props = data["extendedProps"]
        t = Transaction()
        t.title = props["title"]
        t.cents = props["amount"]
        t.date = datetime.fromisoformat(data["start"]).date()
        t.recurrence = props["recurrence"]
        t.week = int(props["week"])
        t.is_income = props["income"]
        t.save()
        if t.recurrence == Recurrence.WEEK:
            while True:
                month = t.date.month
                t.date += timedelta(weeks=t.week)
                if t.date.month == month:
                    t.id = None
                    t.save()
                else:
                    break
        return HttpResponse()

    def patch(self, request: HttpRequest) -> HttpResponse:
        data = json.loads(request.body)
        if "id" in data:
            props = data["extendedProps"]
            t = Transaction.objects.get(id=data["id"])
            t.title = props["title"]
            t.cents = props["amount"]
            t.date = datetime.fromisoformat(data["start"])
            t.recurrence = props["recurrence"]
            t.week = props["week"]
            t.is_income = props["income"]
            t.save()
        return HttpResponse()

    def delete(self, request: HttpRequest) -> HttpResponse:
        data = json.loads(request.body)
        if "id" in data:
            Transaction.objects.get(id=data["id"]).delete()
        return HttpResponse()


class CopyView(View):
    def post(self, request: HttpRequest):
        month = json.loads(request.body)["month"]
        first, last = prev_month_range(month)
        transactions = Transaction.objects.filter(date__range=[first, last], recurrence__in=[Recurrence.WEEK, Recurrence.MONTH])
        for transaction in transactions:
            if transaction.recurrence == Recurrence.MONTH:
                transaction.id = None
                transaction.date = add_months(transaction.date, 1)
                transaction.save()
            else:
                check = transaction.date + timedelta(weeks=transaction.week)
                if check.month != month:
                    continue
                while True:
                    transaction.date += timedelta(weeks=transaction.week)
                    if transaction.date.month == month:
                        transaction.id = None
                        transaction.save()
                    else:
                        break
        return HttpResponse()