From dc387fed02b11332b718c1e0b7224723149c6f41 Mon Sep 17 00:00:00 2001
From: Yirou Qiu <y2qiu@uwaterloo.ca>
Date: Thu, 16 Feb 2023 12:08:59 -0500
Subject: [PATCH] add bill model

---
 core/admin.py                        |  3 ++
 core/api/bill.py                     | 69 ++++++++++++++++++++++++++++
 core/models/bill.py                  | 39 ++++++++++++++++
 core/serializers/OwnerSerializers.py |  5 ++
 core/serializers/bill.py             | 27 +++++++++++
 core/urls.py                         |  5 ++
 6 files changed, 148 insertions(+)
 create mode 100644 core/api/bill.py
 create mode 100644 core/models/bill.py
 create mode 100644 core/serializers/OwnerSerializers.py
 create mode 100644 core/serializers/bill.py

diff --git a/core/admin.py b/core/admin.py
index 8c38f3f..d994f05 100644
--- a/core/admin.py
+++ b/core/admin.py
@@ -1,3 +1,6 @@
 from django.contrib import admin
 
 # Register your models here.
+from core.models.bill import Bill
+
+admin.site.register(Bill)
diff --git a/core/api/bill.py b/core/api/bill.py
new file mode 100644
index 0000000..ef0a6f1
--- /dev/null
+++ b/core/api/bill.py
@@ -0,0 +1,69 @@
+from rest_framework import generics, mixins, status
+from core.models.bill import Bill
+from core.serializers.bill import BillSerializer
+from rest_framework.response import Response
+from rest_framework import permissions, authentication
+
+
+class BillListCreate(mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView):
+    queryset = Bill.objects.all()
+    serializer_class = BillSerializer
+    authentication_classes = [
+        authentication.SessionAuthentication,
+        authentication.TokenAuthentication
+    ]
+    # permission_classes = (permissions.IsAuthenticated,)
+
+    def get(self, request, *args, **kwargs):
+        return self.list(request, *args, **kwargs)
+
+    def post(self, request, *args, **kwargs):
+        serializer = self.get_serializer(data=request.data)
+        serializer.is_valid(raise_exception=True)
+        self.perform_create(serializer)
+        headers = self.get_success_headers(serializer.data)
+        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
+
+    def perform_create(self, serializer):
+        default_user = self.request.user
+        if not default_user:
+            default_user = None
+        # serializer.is_valid()
+        serializer.save(user = default_user)
+
+    def get_queryset(self, *args, **kwargs):
+        qs =super().get_queryset(*args, **kwargs)
+        request = self.request
+        user = request.user
+        if not user.is_authenticated:
+            return Bill.objects.none()
+        return qs.filter(user = user)
+    
+
+
+bill_list_create_api = BillListCreate.as_view()
+
+
+class BillDetail(mixins.RetrieveModelMixin,
+                 mixins.UpdateModelMixin,
+                 mixins.DestroyModelMixin,
+                 generics.GenericAPIView):
+    queryset = Bill.objects.all()
+    serializer_class = BillSerializer
+    authentication_classes = [
+        authentication.SessionAuthentication,
+        authentication.TokenAuthentication
+    ]
+    # permission_classes = (permissions.IsAuthenticated,)
+    lookup_field = "pk"
+
+    def get(self, request, *args, **kwargs):
+        return self.retrieve(request, *args, **kwargs)
+
+    def put(self, request, *args, **kwargs):
+        return self.update(request, *args, **kwargs)
+
+    def delete(self, request, *args, **kwargs):
+        return self.destroy(request, *args, **kwargs)
+
+bill_detail_api = BillDetail.as_view()
diff --git a/core/models/bill.py b/core/models/bill.py
new file mode 100644
index 0000000..f26e86b
--- /dev/null
+++ b/core/models/bill.py
@@ -0,0 +1,39 @@
+from django.db import models
+from django.utils import timezone
+from django.contrib.auth.models import User
+from core.models.utils import UUIDModel
+import datetime
+
+
+class Bill(UUIDModel):
+
+    user = models.ForeignKey(User, default=1, null=True, on_delete=models.SET_NULL)
+    
+    title = models.CharField(max_length = 120)
+    
+    date = models.DateField(verbose_name="payment time", default = datetime.date.today)
+
+    datetime = models.DateTimeField(verbose_name="payment date & time", default = timezone.now)
+
+    price = models.DecimalField(verbose_name='payment amount', max_digits=15, decimal_places=2, default=0.00)
+
+    comment = models.TextField(verbose_name= "comment", blank = True, null = True, default=None)
+
+
+    # need confirmation
+    categories = (
+        (1, "Food"),
+        (2, "Groceries"),
+        (3, "Transportation"),
+        (4, "clothing"),
+        (5, "Entertainment"),
+        (6, "Bill"),
+        (7, "Sports"),
+        (8, "Electronics"),
+        (9, "Travel"),
+        (10, "House & Car"),
+        (11, "Others")
+    )
+
+
+    categories = models.SmallIntegerField(verbose_name="bill categories", choices = categories, default=11)
\ No newline at end of file
diff --git a/core/serializers/OwnerSerializers.py b/core/serializers/OwnerSerializers.py
new file mode 100644
index 0000000..b556045
--- /dev/null
+++ b/core/serializers/OwnerSerializers.py
@@ -0,0 +1,5 @@
+from rest_framework import serializers
+
+class UserSerializer(serializers.Serializer):
+    username = serializers.CharField(read_only=True)
+    email = serializers.CharField(read_only=True)
\ No newline at end of file
diff --git a/core/serializers/bill.py b/core/serializers/bill.py
new file mode 100644
index 0000000..d3dfdff
--- /dev/null
+++ b/core/serializers/bill.py
@@ -0,0 +1,27 @@
+from rest_framework import serializers
+from core.models.bill import Bill
+from rest_framework.reverse import reverse
+from core.serializers.OwnerSerializers import UserSerializer
+
+
+class BillSerializer(serializers.ModelSerializer):
+    url = serializers.SerializerMethodField(read_only=True)
+    user = UserSerializer(read_only=True)
+    class Meta:
+        model = Bill
+        fields = (
+            'user',
+            'url',
+            'title',
+            'date',
+            'datetime',
+            'price',
+            'categories',
+            'comment'
+        )
+    
+    def get_url(self, obj):
+        request = self.context.get("request")
+        if not request:
+            return None
+        return reverse("bill-detail", kwargs = {"pk": obj.pk}, request = request)
\ No newline at end of file
diff --git a/core/urls.py b/core/urls.py
index 7a014bc..f515f05 100644
--- a/core/urls.py
+++ b/core/urls.py
@@ -6,6 +6,7 @@ from core.api.auth import RegisterAPI, LoginAPI, AppleLogin, GoogleLogin, Facebo
 from core.api.password import ChangePasswordView
 from core.api.profile import ProfileViewSet
 from core.api.coupon import CouponViewSet
+from core.api.bill import *
 
 router = routers.DefaultRouter()
 
@@ -28,4 +29,8 @@ urlpatterns += [
     path('api/profile', ProfileViewSet.as_view(), name='profile'),
     # coupon
     path('api/coupon', CouponViewSet.as_view(), name='coupon'),
+
+    # bill
+    path('api/bill/', bill_list_create_api, name="bill-list"),
+    path('api/bill/<uuid:pk>/', bill_detail_api, name="bill-detail")
 ]
-- 
GitLab