Skip to content

Commit

Permalink
Merge branch 'master' of github.com:harunurkst/qard-al-hasana
Browse files Browse the repository at this point in the history
  • Loading branch information
Waislam committed Jul 9, 2023
2 parents d818296 + 13508c0 commit c338399
Show file tree
Hide file tree
Showing 11 changed files with 168 additions and 24 deletions.
17 changes: 17 additions & 0 deletions backend/organization/migrations/0010_team_address.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 4.1.2 on 2023-06-17 16:50

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("organization", "0009_alter_team_owner"),
]

operations = [
migrations.AddField(
model_name="team",
name="address",
field=models.CharField(blank=True, max_length=200),
),
]
23 changes: 17 additions & 6 deletions backend/organization/models.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from django.db import models

from django.contrib.auth.models import (
AbstractBaseUser,
PermissionsMixin,
)
from django.db import models
from django.db.models import Sum

from peoples.models import Staff

Expand All @@ -12,9 +12,11 @@

class BaseModel(models.Model):
branch = models.ForeignKey("organization.Branch", on_delete=models.PROTECT)
organization = models.ForeignKey("organization.Organization", on_delete=models.PROTECT)
organization = models.ForeignKey(
"organization.Organization", on_delete=models.PROTECT)
created_at = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey("organization.User", on_delete=models.SET_NULL, blank=True, null=True)
created_by = models.ForeignKey(
"organization.User", on_delete=models.SET_NULL, blank=True, null=True)


class Division(models.Model):
Expand Down Expand Up @@ -65,7 +67,8 @@ class User(AbstractBaseUser, PermissionsMixin):

is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
branch = models.ForeignKey("organization.Branch", null=True, blank=True, on_delete=models.SET_NULL)
branch = models.ForeignKey(
"organization.Branch", null=True, blank=True, on_delete=models.SET_NULL)
role = models.CharField(max_length=10, choices=ROLES, default=MEMBER)

USERNAME_FIELD = "username"
Expand Down Expand Up @@ -113,11 +116,19 @@ class Team(models.Model):
name = models.CharField(max_length=150)
branch = models.ForeignKey(Branch, on_delete=models.CASCADE)
owner = models.ForeignKey(User, on_delete=models.CASCADE)

address = models.CharField(max_length=200, blank=True)

class Meta:
unique_together = ("name", "branch")

def __str__(self):
return self.name

def total_unpaid_loan(self):
return self.loan_set.filter(is_paid=False).aggregate(Sum('total_due'))['total_due__sum']

def total_deposit(self):
return self.savings_set.filter(transaction_type='deposit').aggregate(Sum('amount'))['amount__sum']

def active_loan(self):
return self.loan_set.filter(is_paid=False).count()
28 changes: 21 additions & 7 deletions backend/organization/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,17 +82,30 @@ def validate(self, attrs):
raise serializers.ValidationError("Refresh token is required")


class TeamSerializer(serializers.ModelSerializer):
class TeamSerializerBase(serializers.ModelSerializer):

class Meta:
model = Team
fields = ('id', 'name', 'owner', 'branch')
fields = ('id', 'name', 'address',)

# def create(self, validated_data):
# team = Team(**validated_data)
# team.branch = validated_data['owner'].branch
# team.save()
# return team

class TeamSerializer(TeamSerializerBase):
class Meta(TeamSerializerBase.Meta):
fields = TeamSerializerBase.Meta.fields + ('owner',)


class TeamDetailSerializer(TeamSerializerBase):

def to_representation(self, instance):
data = super().to_representation(instance)
data.update({
'org_name': instance.branch.organization.name,
'branch_name': instance.branch.name,
'total_unpaid_loan': instance.total_unpaid_loan(),
'total_deposit': instance.total_deposit(),
'active_loan': instance.active_loan()
})
return data


# Staff List Serializer
Expand All @@ -115,3 +128,4 @@ class Meta:
model = Branch
fields = ('id', 'name', 'address', 'cash_in_hand', 'total_deposit', 'total_due_loan')


7 changes: 6 additions & 1 deletion backend/organization/urls.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from django.urls import path

from rest_framework.routers import DefaultRouter

from organization.views import (
TeamCreateListApiView,
TeamRetriveUpdateDestroyView,
BranchReadOnlyModelViewSet,
StaffReadOnlyModelViewSet
)
Expand All @@ -17,9 +19,12 @@

urlpatterns = [

path("teams/", TeamCreateListApiView.as_view(), name="teams")
path("teams/", TeamCreateListApiView.as_view(), name="teams"),

path("teams/<int:pk>/", TeamRetriveUpdateDestroyView.as_view(),
name="team_re_up_delete"),
]

urlpatterns += router.urls


25 changes: 18 additions & 7 deletions backend/organization/views.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
from django.db.models import Count, Q, Sum, Avg, Max, Min

from rest_framework.views import APIView
from rest_framework import viewsets, status
from django.shortcuts import get_object_or_404
from django.db.models import Q, Sum
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.generics import CreateAPIView, ListCreateAPIView
from rest_framework.generics import CreateAPIView, ListCreateAPIView,RetrieveUpdateDestroyAPIView
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView

from peoples.models import Staff
from transaction.models import Savings, Loan
# from transaction.models import Savings, Loan

from .serializers import (
LoginSerializer,
TeamDetailSerializer,
UserSerializer,
UserSerilizerWithToken,
MyRefreshSerializer,
Expand Down Expand Up @@ -45,11 +45,22 @@ def post(self, request, *args, **kwargs):


class TeamCreateListApiView(ListCreateAPIView):
queryset = Team.objects.all()
queryset = Team.objects.all().order_by('-id')
permission_classes = [IsAuthenticated]
serializer_class = TeamSerializer
filterset_fields = ["owner", "branch"]

def perform_create(self, serializer):
serializer.save(branch=serializer.validated_data["owner"].branch)


class TeamRetriveUpdateDestroyView(RetrieveUpdateDestroyAPIView):
permission_classes = [IsAuthenticated]
serializer_class = TeamDetailSerializer

def get_object(self):
return get_object_or_404(Team, id=self.kwargs['pk'])


class StaffReadOnlyModelViewSet(viewsets.ReadOnlyModelViewSet):
""" provides only list and retrieve actions """
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Generated by Django 4.1.2 on 2023-06-18 01:22

from django.db import migrations, models
import django.utils.timezone


class Migration(migrations.Migration):
dependencies = [
("peoples", "0003_remove_staff_branch_remove_staff_role"),
]

operations = [
migrations.AddField(
model_name="member",
name="created_at",
field=models.DateTimeField(
auto_now_add=True, default=django.utils.timezone.now
),
preserve_default=False,
),
migrations.AddField(
model_name="member",
name="updated_at",
field=models.DateTimeField(auto_now=True),
),
]
12 changes: 12 additions & 0 deletions backend/peoples/migrations/0005_merge_20230623_1031.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Generated by Django 4.1.2 on 2023-06-23 04:31

from django.db import migrations


class Migration(migrations.Migration):
dependencies = [
("peoples", "0004_alter_member_mobile_number_alter_staff_mobile_number"),
("peoples", "0004_member_created_at_member_updated_at"),
]

operations = []
2 changes: 2 additions & 0 deletions backend/peoples/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class Member(models.Model):
)
branch = models.ForeignKey("organization.Branch", on_delete=models.CASCADE)
is_active = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

class Meta:
unique_together = ("team", "serial_number")
Expand Down
21 changes: 20 additions & 1 deletion backend/peoples/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,17 @@
class MemberDetailSerializer(serializers.ModelSerializer):
class Meta:
model = Member
fields = '__all__'
fields = ('id', 'name', 'mobile_number', 'guardian_name',
'serial_number', 'team', 'branch', )

def to_representation(self, instance):
data = super().to_representation(instance)
data.update({
"team": instance.team.name,
"branch": instance.branch.name,
"joined_date": instance.created_at
})
return data


class MemberCreateSerializer(serializers.ModelSerializer):
Expand All @@ -28,3 +38,12 @@ def validate_serial_number(self, value):
"Serial number must not be greater than 25."
)
return value


class MemberSavingsLoanInfoSerializer(serializers.Serializer):
total_savings = serializers.IntegerField()
last_loan = serializers.IntegerField()
loan_date = serializers.DateField()
loan_paid = serializers.IntegerField()
installment_paid = serializers.IntegerField()
total_loan_count = serializers.IntegerField()
4 changes: 3 additions & 1 deletion backend/peoples/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
from rest_framework import routers
from peoples.views import (
MemberListCreateView,
MemberDetailsView
MemberDetailsView,
MemberSavingLoanInfo
)


Expand All @@ -13,6 +14,7 @@
urlpatterns = [
path("members/", MemberListCreateView.as_view(), name="list_create"),
path("members/<pk>/", MemberDetailsView.as_view(), name="details"),
path("members/<int:id>/saving-loan-info/", MemberSavingLoanInfo.as_view(), name="saving_loan_info"),
]

urlpatterns += peoples_router.urls
27 changes: 26 additions & 1 deletion backend/peoples/views.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
from django.shortcuts import get_object_or_404
from django.db.models import Sum
from rest_framework import viewsets
from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.filters import SearchFilter, OrderingFilter

from rest_framework.response import Response
from rest_framework import status
from rest_framework.views import APIView
from django_filters.rest_framework import DjangoFilterBackend
from transaction.models import Loan, Savings

# App related
from peoples.models import Member, Staff
from peoples.permissions import IsSameBranch
from peoples.serializers import (
MemberCreateSerializer,
MemberDetailSerializer,
MemberSavingsLoanInfoSerializer,
)


Expand Down Expand Up @@ -41,3 +47,22 @@ def get_queryset(self):



class MemberSavingLoanInfo(APIView):
serializer_class = MemberSavingsLoanInfoSerializer

def get(self, request, *args, **kwargs):
member = get_object_or_404(Member, id=kwargs.get('id'))
savings=Savings.objects.filter(member=member).aggregate(Sum('amount'))['amount__sum']
last_loan = Loan.objects.filter(member=member).last()
total_loan = Loan.objects.filter(member=member).count()

data = {
"total_savings": savings if savings else 0,
"last_loan": last_loan.amount if last_loan else 0,
"loan_date": last_loan.date if last_loan else None,
"loan_paid": last_loan.total_paid if last_loan else 0,
"installment_paid": last_loan.installment_paid if last_loan else 0,
"total_loan_count": total_loan
}
serializer = self.serializer_class(data)
return Response(serializer.data, status=status.HTTP_200_OK)

0 comments on commit c338399

Please sign in to comment.