first base of project-changed apps: Herd-livestock-tag-log-elasticsearch-
This commit is contained in:
@@ -10,8 +10,9 @@ For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/5.2/ref/settings/
|
||||
"""
|
||||
import os.path
|
||||
from pathlib import Path
|
||||
from datetime import timedelta
|
||||
from pathlib import Path
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||
@@ -42,6 +43,7 @@ INSTALLED_APPS = [
|
||||
'rest_framework',
|
||||
"corsheaders",
|
||||
'rest_framework_simplejwt',
|
||||
'rest_framework_simplejwt.token_blacklist',
|
||||
'apps.authentication.apps.AuthenticationConfig',
|
||||
'apps.authorization.apps.AuthorizationConfig',
|
||||
'apps.captcha_app.apps.CaptchaAppConfig',
|
||||
@@ -52,8 +54,10 @@ INSTALLED_APPS = [
|
||||
'apps.tag.apps.TagConfig',
|
||||
'apps.warehouse.apps.WarehouseConfig',
|
||||
'apps.search.apps.SearchConfig',
|
||||
'apps.log.apps.LogConfig',
|
||||
'rest_captcha',
|
||||
'captcha',
|
||||
'drf_yasg'
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
@@ -64,6 +68,8 @@ MIDDLEWARE = [
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
'crum.CurrentRequestUserMiddleware',
|
||||
'apps.log.middlewares.SaveLog'
|
||||
]
|
||||
|
||||
ROOT_URLCONF = 'Rasaddam_Backend.urls'
|
||||
@@ -88,6 +94,14 @@ WSGI_APPLICATION = 'Rasaddam_Backend.wsgi.application'
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/5.2/ref/settings/#databases
|
||||
|
||||
MONGODB_DATABASES = {
|
||||
"default": {
|
||||
"name": 'mongodb',
|
||||
"host": "",
|
||||
"tz_aware": True, # if you using timezones in django (USE_TZ = True) # noqa
|
||||
},
|
||||
}
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.postgresql_psycopg2',
|
||||
@@ -96,11 +110,28 @@ DATABASES = {
|
||||
'USER': "root",
|
||||
'PASSWORD': "aFC3hqbxxR0SeBPZ6TCZ37my",
|
||||
'PORT': '32718'
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
AUTH_USER_MODEL = 'authentication.User'
|
||||
|
||||
SWAGGER_SETTINGS = {
|
||||
'SECURITY_DEFINITIONS': {
|
||||
'Bearer': {
|
||||
'type': 'apiKey',
|
||||
'name': 'Authorization',
|
||||
'in': 'header'
|
||||
},
|
||||
'basic': { # <<-- is for djagno authentication
|
||||
'type': 'basic'
|
||||
},
|
||||
},
|
||||
'USE_SESSION_AUTH': True,
|
||||
}
|
||||
|
||||
LOGIN_URL = 'rest_framework:login'
|
||||
LOGOUT_URL = 'rest_framework:logout'
|
||||
|
||||
REST_FRAMEWORK = {
|
||||
'DEFAULT_PERMISSION_CLASSES': (
|
||||
'rest_framework.permissions.IsAuthenticated',
|
||||
@@ -111,7 +142,8 @@ REST_FRAMEWORK = {
|
||||
'rest_framework.authentication.BasicAuthentication',
|
||||
),
|
||||
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.LimitOffsetPagination",
|
||||
"PAGE_SIZE": 25
|
||||
"PAGE_SIZE": 25,
|
||||
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema'
|
||||
}
|
||||
|
||||
SIMPLE_JWT = {
|
||||
@@ -189,12 +221,11 @@ ELASTICSEARCH_DSL = {
|
||||
# liara elastic password uYkiQ860vLW8DIbWpNjqtz2B # noqa
|
||||
# local system password =z66+LCIebq4NQRR_+=R # noqa
|
||||
"default": {
|
||||
"hosts": "http://damelasticsearch:9200",
|
||||
"hosts": "http://monte-rosa.liara.cloud:31157",
|
||||
"http_auth": ("elastic", "uYkiQ860vLW8DIbWpNjqtz2B"),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators
|
||||
|
||||
@@ -245,6 +276,7 @@ CORS_ORIGIN_WHITELIST = (
|
||||
'http://127.0.0.1:8080',
|
||||
'http://127.0.0.1:3000',
|
||||
'http://localhost:3000',
|
||||
'http://192.168.88.130:3000',
|
||||
'https://rasadyar.net'
|
||||
)
|
||||
|
||||
@@ -253,6 +285,7 @@ CORS_ALLOWED_ORIGINS = (
|
||||
'http://127.0.0.1:8080',
|
||||
'http://127.0.0.1:3000',
|
||||
'http://localhost:3000',
|
||||
'http://192.168.88.130:3000',
|
||||
'https://rasadyar.net'
|
||||
)
|
||||
|
||||
|
||||
@@ -16,10 +16,18 @@ Including another URLconf
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from django.urls import path, include
|
||||
from apps.core.swagger import schema_view
|
||||
|
||||
urlpatterns = [
|
||||
path('admin/', admin.site.urls),
|
||||
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
|
||||
path('auth/', include('apps.authentication.urls')),
|
||||
path('auth/', include('apps.authorization.urls')),
|
||||
path('', include('apps.captcha_app.api.v1.urls')),
|
||||
path('', include('apps.core.urls')),
|
||||
path('herd/', include('apps.herd.urls')),
|
||||
path('livestock/', include('apps.livestock.urls')),
|
||||
path('tag/', include('apps.tag.urls')),
|
||||
path('search/', include('apps.search.urls')),
|
||||
path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
|
||||
]
|
||||
|
||||
@@ -1,35 +1,197 @@
|
||||
import typing
|
||||
|
||||
from apps.authentication.api.v1.serializers.jwt import CustomizedTokenObtainPairSerializer
|
||||
from rest_framework_simplejwt.authentication import JWTAuthentication
|
||||
from rest_framework.decorators import action, permission_classes
|
||||
from apps.authentication import permissions as auth_permissions
|
||||
from apps.authentication.api.v1.serializers.serializer import (
|
||||
CitySerializer,
|
||||
ProvinceSerializer,
|
||||
OrganizationTypeSerializer,
|
||||
OrganizationSerializer,
|
||||
UserSerializer,
|
||||
BankAccountSerializer
|
||||
)
|
||||
from rest_framework_simplejwt.views import TokenObtainPairView
|
||||
from apps.authorization.api.v1 import api as authorize_view
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
from rest_framework.decorators import action
|
||||
from apps.authentication.models import User
|
||||
from rest_framework.views import APIView
|
||||
from apps.authentication.models import (
|
||||
User,
|
||||
City,
|
||||
Province,
|
||||
Organization,
|
||||
OrganizationType,
|
||||
BankAccountInformation
|
||||
)
|
||||
from django.db import transaction
|
||||
from rest_framework.response import Response
|
||||
from common.tools import CustomOperations
|
||||
from rest_framework import status
|
||||
|
||||
|
||||
class CustomizedTokenObtainPairView(TokenObtainPairView):
|
||||
""" Generate Customize token """
|
||||
serializer_class = CustomizedTokenObtainPairSerializer
|
||||
|
||||
|
||||
# Example Code
|
||||
class Authentication(ModelViewSet):
|
||||
queryset = User
|
||||
serializer_class = ''
|
||||
permission_classes = ''
|
||||
authentication_classes = [JWTAuthentication]
|
||||
|
||||
@action(
|
||||
methods=['post', ],
|
||||
detail=False,
|
||||
name='login',
|
||||
url_name='login',
|
||||
url_path='login'
|
||||
)
|
||||
@transaction.atomic
|
||||
def login(self, request):
|
||||
pass
|
||||
|
||||
|
||||
class UserViewSet(ModelViewSet):
|
||||
pass
|
||||
""" Crud operations for user model """
|
||||
queryset = User.objects.all()
|
||||
serializer_class = UserSerializer
|
||||
permission_classes = [
|
||||
auth_permissions.CreateUser,
|
||||
]
|
||||
|
||||
@transaction.atomic
|
||||
def create(self, request, *args, **kwargs):
|
||||
"""
|
||||
Customizing create user & bank account information with
|
||||
permission levels
|
||||
"""
|
||||
|
||||
serializer = self.serializer_class(data=request.data)
|
||||
if serializer.is_valid():
|
||||
user = serializer.save()
|
||||
if 'organization' in request.data.keys():
|
||||
organization = CustomOperations().custom_create( # create organization for user
|
||||
request=request,
|
||||
view=OrganizationViewSet(),
|
||||
data_key='organization'
|
||||
)
|
||||
else:
|
||||
organization = {}
|
||||
if 'user_relations' in request.data.keys():
|
||||
user_relations = CustomOperations().custom_create( # create user relations
|
||||
user=user,
|
||||
request=request,
|
||||
view=authorize_view.UserRelationViewSet(),
|
||||
data_key='user_relations',
|
||||
additional_data={'organization': organization['id']} # noqa
|
||||
)
|
||||
else:
|
||||
user_relations = {}
|
||||
if 'bank_account' in request.data.keys():
|
||||
bank_account = CustomOperations().custom_create( # create user bank account info
|
||||
user=user,
|
||||
request=request,
|
||||
view=BankAccountViewSet(),
|
||||
data_key='bank_account'
|
||||
)
|
||||
else:
|
||||
bank_account = {}
|
||||
serializer_data = serializer.data
|
||||
serializer_data.update({
|
||||
'organization': organization,
|
||||
'user_relations': user_relations, # noqa
|
||||
'bank_account': bank_account # noqa
|
||||
})
|
||||
return Response(serializer_data, status=status.HTTP_201_CREATED)
|
||||
else:
|
||||
return Response(serializer.errors, status=status.HTTP_403_FORBIDDEN)
|
||||
|
||||
@transaction.atomic
|
||||
def update(self, request, pk=None, *args, **kwargs):
|
||||
"""
|
||||
Customizing update user & bank account info with
|
||||
permission levels
|
||||
"""
|
||||
serializer = self.serializer_class(data=request.data)
|
||||
if serializer.is_valid():
|
||||
user = serializer.update(self.queryset.get(id=pk), validated_data=request.data)
|
||||
if 'organization' in request.data.keys(): # noqa
|
||||
organization = CustomOperations().custom_update( # update organization for user
|
||||
request=request,
|
||||
view=OrganizationViewSet(),
|
||||
data_key='organization',
|
||||
obj_id=request.data['organization']['id']
|
||||
)
|
||||
else:
|
||||
organization = {}
|
||||
if 'user_relations' in request.data.keys():
|
||||
user_relations = CustomOperations().custom_update( # update user relations
|
||||
user=user,
|
||||
request=request,
|
||||
view=authorize_view.UserRelationViewSet(),
|
||||
data_key='user_relations',
|
||||
additional_data={'organization': request.data['organization']['id']}, # noqa
|
||||
obj_id=request.data['user_relations']['id']
|
||||
)
|
||||
else:
|
||||
user_relations = {}
|
||||
if 'bank_account' in request.data.keys():
|
||||
bank_account = CustomOperations().custom_update( # update user bank account info
|
||||
user=user,
|
||||
request=request,
|
||||
view=BankAccountViewSet(),
|
||||
data_key='bank_account',
|
||||
obj_id=request.data['bank_account']['id']
|
||||
)
|
||||
else:
|
||||
bank_account = {}
|
||||
serializer_data = serializer.data
|
||||
serializer_data.update({
|
||||
'organization': organization,
|
||||
'user_relations': user_relations, # noqa
|
||||
'bank_account': bank_account # noqa
|
||||
})
|
||||
return Response(serializer_data, status=status.HTTP_200_OK)
|
||||
else:
|
||||
return Response(serializer.errors, status=status.HTTP_403_FORBIDDEN)
|
||||
|
||||
|
||||
class CityViewSet(ModelViewSet):
|
||||
""" Crud operations for city model """ #
|
||||
queryset = City.objects.all()
|
||||
serializer_class = CitySerializer
|
||||
|
||||
|
||||
class ProvinceViewSet(ModelViewSet):
|
||||
""" Crud operations for province model """ #
|
||||
queryset = Province.objects.all()
|
||||
serializer_class = ProvinceSerializer
|
||||
|
||||
|
||||
class OrganizationTypeViewSet(ModelViewSet):
|
||||
""" Crud operations for Organization Type model """ #
|
||||
queryset = OrganizationType.objects.all()
|
||||
serializer_class = OrganizationTypeSerializer
|
||||
|
||||
|
||||
class OrganizationViewSet(ModelViewSet):
|
||||
""" Crud operations for organization model """ #
|
||||
queryset = Organization.objects.all()
|
||||
serializer_class = OrganizationSerializer
|
||||
permission_classes = [auth_permissions.CreateOrganization]
|
||||
|
||||
@transaction.atomic
|
||||
def create(self, request, *args, **kwargs):
|
||||
"""
|
||||
@create Organization by user
|
||||
"""
|
||||
serializer = self.serializer_class(data=request.data['organization'])
|
||||
|
||||
if serializer.is_valid():
|
||||
organization = serializer.save()
|
||||
|
||||
if 'user_relations' in request.data.keys():
|
||||
user_relations = CustomOperations().custom_create( # create user relations
|
||||
request=request,
|
||||
view=authorize_view.UserRelationViewSet(),
|
||||
data_key='user_relations',
|
||||
additional_data={'organization': organization.id} # noqa
|
||||
)
|
||||
serializer_data = serializer.data
|
||||
serializer_data.update(
|
||||
{'user_relations': user_relations}
|
||||
)
|
||||
return Response(serializer_data, status=status.HTTP_201_CREATED)
|
||||
else:
|
||||
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
||||
else:
|
||||
return Response(serializer.errors, status=status.HTTP_406_NOT_ACCEPTABLE)
|
||||
|
||||
|
||||
class BankAccountViewSet(ModelViewSet):
|
||||
""" Crud operations for bank account model """ #
|
||||
queryset = BankAccountInformation.objects.all()
|
||||
serializer_class = BankAccountSerializer
|
||||
|
||||
@@ -1,53 +1,53 @@
|
||||
from apps.authentication.api.v1.serializers.serializer import UserSerializer
|
||||
from rest_framework.pagination import LimitOffsetPagination
|
||||
from rest_framework.viewsets import ModelViewSet, ViewSet
|
||||
from apps.authentication.documents import UserDocument
|
||||
from rest_framework.response import Response
|
||||
from django.http.response import HttpResponse
|
||||
from apps.authentication.models import User
|
||||
from rest_framework.views import APIView
|
||||
from elasticsearch_dsl.query import Q
|
||||
import abc
|
||||
|
||||
|
||||
class PaginatedElasticSearchApiView(APIView, LimitOffsetPagination):
|
||||
"""Base ApiView Class for elasticsearch views with pagination
|
||||
Other ApiView classes should inherit from this class"""
|
||||
serializer_class = None
|
||||
document_class = None
|
||||
|
||||
@abc.abstractmethod
|
||||
def generate_q_expression(self, query):
|
||||
"""This method should be overridden
|
||||
and return a Q() expression."""
|
||||
|
||||
def get(self, request, query):
|
||||
try:
|
||||
q = self.generate_q_expression(query)
|
||||
search = self.document_class.search().query(q)
|
||||
response = search.execute()
|
||||
|
||||
print(f"Found {response.hits.total.value} hit(s) for query: '{query}'")
|
||||
|
||||
results = self.paginate_queryset(response, request, view=self) # noqa
|
||||
serializer = self.serializer_class(results, many=True)
|
||||
return self.get_paginated_response(serializer.data)
|
||||
except Exception as e:
|
||||
return HttpResponse(e, status=500)
|
||||
|
||||
|
||||
class SearchUsersApiView(PaginatedElasticSearchApiView): # noqa
|
||||
"""Search in Users"""
|
||||
|
||||
serializer_class = UserSerializer
|
||||
document_class = UserDocument
|
||||
|
||||
def generate_q_expression(self, query):
|
||||
return Q(
|
||||
'multi_match',
|
||||
query=query,
|
||||
fields=[
|
||||
'username',
|
||||
'mobile'
|
||||
], fuzziness='auto'
|
||||
)
|
||||
# from apps.authentication.api.v1.serializers.serializer import UserSerializer
|
||||
# from rest_framework.pagination import LimitOffsetPagination
|
||||
# from rest_framework.viewsets import ModelViewSet, ViewSet
|
||||
# from apps.authentication.document import UserDocument
|
||||
# from rest_framework.response import Response
|
||||
# from django.http.response import HttpResponse
|
||||
# from apps.authentication.models import User
|
||||
# from rest_framework.views import APIView
|
||||
# from elasticsearch_dsl.query import Q
|
||||
# import abc
|
||||
#
|
||||
#
|
||||
# class PaginatedElasticSearchApiView(APIView, LimitOffsetPagination):
|
||||
# """Base ApiView Class for elasticsearch views with pagination,
|
||||
# Other ApiView classes should inherit from this class"""
|
||||
# serializer_class = None
|
||||
# document_class = None
|
||||
#
|
||||
# @abc.abstractmethod
|
||||
# def generate_q_expression(self, query):
|
||||
# """This method should be overridden
|
||||
# and return a Q() expression."""
|
||||
#
|
||||
# def get(self, request, query):
|
||||
# try:
|
||||
# q = self.generate_q_expression(query)
|
||||
# search = self.document_class.search().query(q)
|
||||
# response = search.execute()
|
||||
#
|
||||
# print(f"Found {response.hits.total.value} hit(s) for query: '{query}'")
|
||||
#
|
||||
# results = self.paginate_queryset(response, request, view=self) # noqa
|
||||
# serializer = self.serializer_class(results, many=True)
|
||||
# return self.get_paginated_response(serializer.data)
|
||||
# except Exception as e:
|
||||
# return HttpResponse(e, status=500)
|
||||
#
|
||||
#
|
||||
# class SearchUsersApiView(PaginatedElasticSearchApiView): # noqa
|
||||
# """Search in Users"""
|
||||
#
|
||||
# serializer_class = UserSerializer
|
||||
# document_class = UserDocument
|
||||
#
|
||||
# def generate_q_expression(self, query):
|
||||
# return Q(
|
||||
# 'multi_match',
|
||||
# query=query,
|
||||
# fields=[
|
||||
# 'username',
|
||||
# 'mobile'
|
||||
# ], fuzziness='auto'
|
||||
# )
|
||||
|
||||
@@ -1,11 +1,179 @@
|
||||
from apps.authorization.api.v1.serializers import UserRelationSerializer
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import serializers
|
||||
from apps.authentication.models import User
|
||||
from apps.authentication.models import (
|
||||
User,
|
||||
City,
|
||||
Province,
|
||||
Organization,
|
||||
OrganizationType,
|
||||
BankAccountInformation
|
||||
)
|
||||
from apps.authorization import models as authorize_models
|
||||
import typing
|
||||
|
||||
|
||||
class CitySerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = City
|
||||
fields = [
|
||||
'id',
|
||||
'name'
|
||||
]
|
||||
|
||||
|
||||
class ProvinceSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Province
|
||||
fields = [
|
||||
'id',
|
||||
'name'
|
||||
]
|
||||
|
||||
|
||||
class BankAccountSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = BankAccountInformation
|
||||
fields = [
|
||||
'id',
|
||||
'user',
|
||||
'account',
|
||||
'name',
|
||||
'card',
|
||||
'sheba'
|
||||
]
|
||||
extra_kwargs = {
|
||||
'user': {'required': False},
|
||||
'account': {'required': False},
|
||||
'card': {'required': False},
|
||||
'sheba': {'required': False}
|
||||
}
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
""" update user bank account information """
|
||||
instance.name = validated_data.get('name', instance.name)
|
||||
instance.account = validated_data.get('account', instance.account)
|
||||
instance.card = validated_data.get('card', instance.card)
|
||||
instance.sheba = validated_data.get('sheba', instance.sheba)
|
||||
instance.save()
|
||||
return instance
|
||||
|
||||
|
||||
class UserSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = User
|
||||
fields = [
|
||||
'id',
|
||||
'username',
|
||||
'mobile'
|
||||
'password',
|
||||
'first_name',
|
||||
'last_name',
|
||||
'is_active',
|
||||
'mobile',
|
||||
'phone',
|
||||
'national_code',
|
||||
'birthdate',
|
||||
'nationality',
|
||||
'ownership',
|
||||
'address',
|
||||
'photo',
|
||||
'province',
|
||||
'city',
|
||||
'otp_status',
|
||||
]
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
""" update user instance """
|
||||
instance.username = validated_data.get('username', instance.username)
|
||||
instance.password = validated_data.get('password', instance.password)
|
||||
instance.first_name = validated_data.get('first_name')
|
||||
instance.last_name = validated_data.get('last_name')
|
||||
instance.is_active = validated_data.get('is_active')
|
||||
instance.mobile = validated_data.get('mobile')
|
||||
instance.phone = validated_data.get('phone')
|
||||
instance.national_code = validated_data.get('national_code')
|
||||
instance.birthdate = validated_data.get('birthdate')
|
||||
instance.nationality = validated_data.get('nationality')
|
||||
instance.ownership = validated_data.get('ownership')
|
||||
instance.address = validated_data.get('address')
|
||||
instance.photo = validated_data.get('photo')
|
||||
instance.province = Province.objects.get(id=validated_data.get('province'))
|
||||
instance.city = City.objects.get(id=validated_data.get('city'))
|
||||
instance.otp_status = validated_data.get('otp_status')
|
||||
instance.save()
|
||||
|
||||
return instance
|
||||
|
||||
@staticmethod
|
||||
def update_relations(user: object, relation_data: dict, bank_data: dict) -> typing.Any:
|
||||
"""
|
||||
update user relations & bank account for user
|
||||
"""
|
||||
user_relation = UserRelationSerializer(data=relation_data) # Create user relation
|
||||
if user_relation.is_valid(raise_exception=True):
|
||||
user_relation_obj = user_relation.update(
|
||||
authorize_models.UserRelations.objects.get(user=user),
|
||||
validated_data=relation_data
|
||||
)
|
||||
|
||||
bank_info = BankAccountSerializer(data=bank_data) # Create user bank information
|
||||
if bank_info.is_valid(raise_exception=True):
|
||||
bank_obj = bank_info.update(
|
||||
BankAccountInformation.objects.get(id=bank_data['id']),
|
||||
validated_data=bank_data
|
||||
)
|
||||
|
||||
return user_relation_obj, bank_obj # noqa
|
||||
|
||||
|
||||
class OrganizationTypeSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = OrganizationType
|
||||
fields = [
|
||||
'id',
|
||||
'key',
|
||||
'name',
|
||||
]
|
||||
|
||||
|
||||
class OrganizationSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Organization
|
||||
fields = [
|
||||
'id',
|
||||
'name',
|
||||
'type',
|
||||
'province',
|
||||
'city',
|
||||
'parent_organization',
|
||||
'national_unique_id'
|
||||
]
|
||||
extra_kwargs = {}
|
||||
|
||||
def to_representation(self, instance):
|
||||
representation = super().to_representation(instance)
|
||||
if isinstance(instance, Organization):
|
||||
representation['province'] = ProvinceSerializer(instance.province).data
|
||||
representation['city'] = CitySerializer(instance.city).data
|
||||
representation['type'] = OrganizationTypeSerializer(instance.type).data
|
||||
if instance.parent_organization:
|
||||
representation['parent_organization'] = OrganizationSerializer(instance.parent_organization).data
|
||||
|
||||
return representation
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
""" update user organization information """ # noqa
|
||||
instance.name = validated_data.get('name', instance.name)
|
||||
if validated_data.get('type'):
|
||||
instance.type = OrganizationType.objects.get(id=validated_data.get('type', instance.type))
|
||||
if validated_data.get('province'):
|
||||
instance.province = Province.objects.get(id=validated_data.get('province', instance.province))
|
||||
if validated_data.get('city'):
|
||||
instance.city = City.objects.get(id=validated_data.get('city', instance.city))
|
||||
if validated_data.get('parent_organization'):
|
||||
instance.parent_organization = Organization.objects.get(
|
||||
id=validated_data.get('parent_organization', instance.parent_organization)
|
||||
)
|
||||
instance.national_unique_id = validated_data.get('national_unique_id', instance.national_unique_id)
|
||||
instance.save()
|
||||
return instance
|
||||
|
||||
@@ -3,16 +3,29 @@ from rest_framework.routers import DefaultRouter
|
||||
from rest_framework_simplejwt.views import (
|
||||
TokenObtainPairView,
|
||||
TokenRefreshView,
|
||||
TokenVerifyView
|
||||
TokenVerifyView,
|
||||
TokenBlacklistView
|
||||
)
|
||||
from .api import (
|
||||
CustomizedTokenObtainPairView
|
||||
CustomizedTokenObtainPairView,
|
||||
UserViewSet,
|
||||
CityViewSet,
|
||||
ProvinceViewSet,
|
||||
OrganizationViewSet,
|
||||
OrganizationTypeViewSet
|
||||
)
|
||||
from .search_view import SearchUsersApiView
|
||||
|
||||
router = DefaultRouter()
|
||||
router.register(r'user', UserViewSet, basename='user')
|
||||
router.register(r'city', CityViewSet, basename='city')
|
||||
router.register(r'province', ProvinceViewSet, basename='province')
|
||||
router.register(r'organization', OrganizationViewSet, basename='organization')
|
||||
router.register(r'organization-type', OrganizationTypeViewSet, basename='organization_type')
|
||||
|
||||
urlpatterns = [
|
||||
path('login/', CustomizedTokenObtainPairView.as_view(), name='token_obtain_pair'),
|
||||
path('search_user/<str:query>', SearchUsersApiView.as_view(), name='search_user'),
|
||||
path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
|
||||
path('token/verify/', TokenVerifyView.as_view(), name='token_verify'),
|
||||
path('token/revoke/', TokenBlacklistView.as_view(), name='revoke_token'),
|
||||
path('', include(router.urls))
|
||||
]
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
from .models import User, Province
|
||||
from django_elasticsearch_dsl import Document, fields
|
||||
from django_elasticsearch_dsl.registries import registry
|
||||
|
||||
|
||||
@registry.register_document
|
||||
class UserDocument(Document):
|
||||
"""ElasticSearch Document for indexing users"""
|
||||
|
||||
class Index:
|
||||
name = 'users'
|
||||
settings = {
|
||||
'number_of_shards': 1,
|
||||
'number_of_replicas': 0 # number of copies from data in document
|
||||
}
|
||||
|
||||
class Django:
|
||||
model = User
|
||||
fields = [
|
||||
"id",
|
||||
"username",
|
||||
"mobile",
|
||||
"nationality"
|
||||
]
|
||||
# from .models import User, Province
|
||||
# from django_elasticsearch_dsl import Document, fields
|
||||
# from django_elasticsearch_dsl.registries import registry
|
||||
#
|
||||
#
|
||||
# @registry.register_document
|
||||
# class UserDocument(Document):
|
||||
# """ElasticSearch Document for indexing users"""
|
||||
#
|
||||
# class Index:
|
||||
# name = 'users'
|
||||
# settings = {
|
||||
# 'number_of_shards': 1,
|
||||
# 'number_of_replicas': 0 # number of copies from data in document
|
||||
# }
|
||||
#
|
||||
# class Django:
|
||||
# model = User
|
||||
# fields = [
|
||||
# "id",
|
||||
# "username",
|
||||
# "mobile",
|
||||
# "nationality"
|
||||
# ]
|
||||
|
||||
18
apps/authentication/managers.py
Normal file
18
apps/authentication/managers.py
Normal file
@@ -0,0 +1,18 @@
|
||||
from django.db import models
|
||||
from typing import Any
|
||||
from apps.authentication import models as authentication_models
|
||||
from apps.authorization import models as authorization_models
|
||||
|
||||
|
||||
class UserManager(models.Manager):
|
||||
|
||||
@staticmethod
|
||||
def get_user_information(self, user_id: int) -> Any:
|
||||
""" get user information in 3 models and return 3 objects """
|
||||
user = super().get_queryset().get(id=user_id)
|
||||
yield user
|
||||
bank = authentication_models.BankAccountInformation.objects.get(user_id=user_id)
|
||||
yield bank
|
||||
user_relation = authorization_models.objects.get(user_id=user_id)
|
||||
yield user_relation
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-10 08:51
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authentication', '0007_user_ownership'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='organization',
|
||||
name='type',
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='OrganizationType',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('create_date', models.DateTimeField(auto_now_add=True)),
|
||||
('modify_date', models.DateTimeField(auto_now=True)),
|
||||
('trash', models.BooleanField(default=False)),
|
||||
('key', models.CharField(choices=[('J', 'Jihad'), ('U', 'Union'), ('CO', 'Cooperative'), ('CMP', 'Companies')], max_length=3)),
|
||||
('name', models.CharField(max_length=50, null=True)),
|
||||
('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL)),
|
||||
('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
]
|
||||
19
apps/authentication/migrations/0009_organization_type.py
Normal file
19
apps/authentication/migrations/0009_organization_type.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-10 08:52
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authentication', '0008_remove_organization_type_organizationtype'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='organization',
|
||||
name='type',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='organization_type', to='authentication.organizationtype'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,49 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-13 06:28
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authentication', '0009_organization_type'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='organization',
|
||||
name='company_code',
|
||||
field=models.CharField(default='empty', max_length=30),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='organization',
|
||||
name='field_of_activity',
|
||||
field=models.CharField(choices=[('CO', 'Country'), ('PR', 'Province'), ('CI', 'City')], default='EM', max_length=2),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='is_herd_owner',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='BankAccountInformation',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('create_date', models.DateTimeField(auto_now_add=True)),
|
||||
('modify_date', models.DateTimeField(auto_now=True)),
|
||||
('trash', models.BooleanField(default=False)),
|
||||
('name', models.CharField(max_length=150)),
|
||||
('card', models.CharField(max_length=25, unique=True)),
|
||||
('account', models.CharField(max_length=25, unique=True)),
|
||||
('sheba', models.CharField(max_length=30, unique=True)),
|
||||
('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL)),
|
||||
('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL)),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='bank_information', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-13 06:32
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authentication', '0010_organization_company_code_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='organization',
|
||||
name='national_unique_id',
|
||||
field=models.CharField(default='0', max_length=30),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-13 07:01
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authentication', '0011_organization_national_unique_id'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='organization',
|
||||
name='national_unique_id',
|
||||
field=models.CharField(default='0', max_length=30, unique=True),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,61 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-17 06:01
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authentication', '0012_alter_organization_national_unique_id'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='bankaccountinformation',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='bankaccountinformation',
|
||||
name='modified_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='city',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='city',
|
||||
name='modified_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='organization',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='organization',
|
||||
name='modified_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='organizationtype',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='organizationtype',
|
||||
name='modified_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='province',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='province',
|
||||
name='modified_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='user',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='user',
|
||||
name='modified_by',
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,73 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-17 06:24
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authentication', '0013_remove_bankaccountinformation_created_by_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='bankaccountinformation',
|
||||
name='created_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='bankaccountinformation',
|
||||
name='modified_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='city',
|
||||
name='created_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='city',
|
||||
name='modified_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='organization',
|
||||
name='created_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='organization',
|
||||
name='modified_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='organizationtype',
|
||||
name='created_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='organizationtype',
|
||||
name='modified_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='province',
|
||||
name='created_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='province',
|
||||
name='modified_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='created_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='modified_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,61 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-17 06:27
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authentication', '0014_bankaccountinformation_created_by_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='bankaccountinformation',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='bankaccountinformation',
|
||||
name='modified_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='city',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='city',
|
||||
name='modified_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='organization',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='organization',
|
||||
name='modified_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='organizationtype',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='organizationtype',
|
||||
name='modified_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='province',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='province',
|
||||
name='modified_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='user',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='user',
|
||||
name='modified_by',
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,75 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-17 06:29
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authentication', '0015_remove_bankaccountinformation_created_by_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='bankaccountinformation',
|
||||
name='created_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createddby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='bankaccountinformation',
|
||||
name='modified_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='city',
|
||||
name='created_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createddby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='city',
|
||||
name='modified_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='organization',
|
||||
name='created_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createddby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='organization',
|
||||
name='modified_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='organizationtype',
|
||||
name='created_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createddby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='organizationtype',
|
||||
name='modified_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='province',
|
||||
name='created_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createddby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='province',
|
||||
name='modified_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='created_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createddby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='modified_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,73 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-17 06:35
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authentication', '0016_bankaccountinformation_created_by_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='bankaccountinformation',
|
||||
name='creator_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='bankaccountinformation',
|
||||
name='modifier_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='city',
|
||||
name='creator_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='city',
|
||||
name='modifier_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='organization',
|
||||
name='creator_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='organization',
|
||||
name='modifier_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='organizationtype',
|
||||
name='creator_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='organizationtype',
|
||||
name='modifier_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='province',
|
||||
name='creator_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='province',
|
||||
name='modifier_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='creator_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='modifier_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
]
|
||||
@@ -1,8 +1,9 @@
|
||||
from django.db import models
|
||||
from django.contrib.auth.hashers import make_password
|
||||
from django.contrib.auth.models import (
|
||||
AbstractUser
|
||||
)
|
||||
from apps.core.models import BaseModel
|
||||
from django.db import models
|
||||
|
||||
|
||||
class User(AbstractUser, BaseModel):
|
||||
@@ -36,15 +37,17 @@ class User(AbstractUser, BaseModel):
|
||||
null=True
|
||||
)
|
||||
otp_status = models.BooleanField(default=False)
|
||||
is_herd_owner = models.BooleanField(default=False)
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.username} {self.last_name}-{self.last_login}'
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
self.password = make_password(self.password)
|
||||
super(User, self).save(*args, **kwargs)
|
||||
|
||||
|
||||
class Province(BaseModel):
|
||||
class Province(BaseModel): # noqa
|
||||
name = models.CharField(max_length=50)
|
||||
|
||||
def __str__(self):
|
||||
@@ -64,9 +67,39 @@ class City(BaseModel):
|
||||
super(City, self).save(*args, **kwargs)
|
||||
|
||||
|
||||
class OrganizationType(BaseModel):
|
||||
organization_keys = (
|
||||
('J', 'Jihad'),
|
||||
('U', 'Union'),
|
||||
('CO', 'Cooperative'),
|
||||
('CMP', 'Companies')
|
||||
)
|
||||
key = models.CharField(choices=organization_keys, max_length=3)
|
||||
name = models.CharField(max_length=50, null=True)
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.key}-{self.name}'
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
super(OrganizationType, self).save(*args, **kwargs)
|
||||
|
||||
|
||||
class Organization(BaseModel):
|
||||
name = models.CharField(max_length=50)
|
||||
type = models.CharField(max_length=50)
|
||||
type = models.ForeignKey(
|
||||
'OrganizationType',
|
||||
on_delete=models.CASCADE,
|
||||
related_name="organization_type",
|
||||
null=True
|
||||
)
|
||||
national_unique_id = models.CharField(max_length=30, default="0", unique=True)
|
||||
activity_fields = (
|
||||
('CO', 'Country'),
|
||||
('PR', 'Province'),
|
||||
('CI', 'City')
|
||||
)
|
||||
field_of_activity = models.CharField(max_length=2, choices=activity_fields, default='EM')
|
||||
company_code = models.CharField(max_length=30, default="empty")
|
||||
province = models.ForeignKey(
|
||||
Province,
|
||||
on_delete=models.CASCADE,
|
||||
@@ -91,3 +124,21 @@ class Organization(BaseModel):
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
super(Organization, self).save(*args, **kwargs)
|
||||
|
||||
|
||||
class BankAccountInformation(BaseModel):
|
||||
user = models.ForeignKey(
|
||||
User,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="bank_information"
|
||||
)
|
||||
name = models.CharField(max_length=150)
|
||||
card = models.CharField(max_length=25, unique=True)
|
||||
account = models.CharField(max_length=25, unique=True)
|
||||
sheba = models.CharField(max_length=30, unique=True)
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.name}-{self.card}'
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
super(BankAccountInformation, self).save(*args, **kwargs)
|
||||
|
||||
57
apps/authentication/permissions.py
Normal file
57
apps/authentication/permissions.py
Normal file
@@ -0,0 +1,57 @@
|
||||
from apps.authorization import models as authorize_models
|
||||
from apps.authentication.models import OrganizationType
|
||||
from apps.core import permissions
|
||||
|
||||
|
||||
class CreateUser(permissions.BasePermission):
|
||||
"""
|
||||
@permission: superuser can add users
|
||||
"""
|
||||
|
||||
def has_permission(self, request, view):
|
||||
user_level_info = self.get_user_permissions(request, view)
|
||||
if 'superuser' in user_level_info['permissions']:
|
||||
if 'organization' in request.data.keys():
|
||||
org_type = OrganizationType.objects.get( # noqa
|
||||
id=request.data['organization']['type']
|
||||
)
|
||||
print(org_type.key)
|
||||
if 'J' in user_level_info['organization_type']:
|
||||
return True
|
||||
if 'U' in user_level_info['organization_type']:
|
||||
if org_type.key == 'J' or org_type.key == 'U':
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
if 'CO' in user_level_info['organization_type']:
|
||||
if org_type.key == 'J' or org_type.key == 'U' or org_type.key == 'CO':
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
return True
|
||||
|
||||
|
||||
class CreateOrganization(permissions.BasePermission):
|
||||
"""
|
||||
@permission for adding organization
|
||||
"""
|
||||
|
||||
def has_permission(self, request, view):
|
||||
user_level_info = self.get_user_permissions(request, view)
|
||||
if 'superuser' in user_level_info['permissions']:
|
||||
org_type = OrganizationType.objects.get( # noqa
|
||||
id=request.data['organization']['type']
|
||||
)
|
||||
print(org_type.key)
|
||||
if 'J' in user_level_info['organization_type']:
|
||||
return True
|
||||
if 'U' in user_level_info['organization_type']:
|
||||
if org_type.key == 'J' or org_type.key == 'U':
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
if 'CO' in user_level_info['organization_type']:
|
||||
if org_type.key == 'J' or org_type.key == 'U' or org_type.key == 'CO':
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
0
apps/authorization/api/__init__.py
Normal file
0
apps/authorization/api/__init__.py
Normal file
0
apps/authorization/api/v1/__init__.py
Normal file
0
apps/authorization/api/v1/__init__.py
Normal file
36
apps/authorization/api/v1/api.py
Normal file
36
apps/authorization/api/v1/api.py
Normal file
@@ -0,0 +1,36 @@
|
||||
from rest_framework_simplejwt.authentication import JWTAuthentication
|
||||
from rest_framework.permissions import AllowAny, IsAuthenticated
|
||||
from apps.authorization.api.v1.serializers import (
|
||||
RoleSerializer,
|
||||
PermissionSerializer,
|
||||
UserRelationSerializer
|
||||
)
|
||||
from rest_framework.response import Response
|
||||
from apps.authorization.models import (
|
||||
Role,
|
||||
Permissions,
|
||||
UserRelations
|
||||
)
|
||||
from rest_framework import viewsets
|
||||
|
||||
|
||||
class RoleViewSet(viewsets.ModelViewSet):
|
||||
""" Crud Operations For User Roles """
|
||||
|
||||
queryset = Role.objects.all()
|
||||
serializer_class = RoleSerializer
|
||||
|
||||
|
||||
class PermissionViewSet(viewsets.ModelViewSet):
|
||||
""" Crud Operations for Permissions """
|
||||
|
||||
queryset = Permissions.objects.all()
|
||||
serializer_class = PermissionSerializer
|
||||
|
||||
|
||||
class UserRelationViewSet(viewsets.ModelViewSet):
|
||||
""" Crud Operations for User Relations """
|
||||
|
||||
queryset = UserRelations.objects.all()
|
||||
serializer_class = UserRelationSerializer
|
||||
|
||||
81
apps/authorization/api/v1/serializers.py
Normal file
81
apps/authorization/api/v1/serializers.py
Normal file
@@ -0,0 +1,81 @@
|
||||
from rest_framework import serializers
|
||||
from apps.authorization.models import (
|
||||
Role,
|
||||
Permissions,
|
||||
UserRelations
|
||||
)
|
||||
from apps.authentication.api.v1.serializers import serializer as auth_serializer
|
||||
from apps.authentication.models import Organization
|
||||
|
||||
|
||||
class PermissionSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Permissions
|
||||
fields = [
|
||||
'id',
|
||||
'name',
|
||||
'description'
|
||||
]
|
||||
|
||||
|
||||
class RoleSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Role
|
||||
fields = [
|
||||
'id',
|
||||
'role_name',
|
||||
'description',
|
||||
'type',
|
||||
'permissions'
|
||||
]
|
||||
extra_kwargs = {
|
||||
'permissions': {'required': False} # permissions not required for some roles
|
||||
}
|
||||
|
||||
def to_representation(self, instance):
|
||||
"""
|
||||
using @to_representation for many_to_many permissions in response
|
||||
"""
|
||||
representation = super().to_representation(instance)
|
||||
representation['type'] = auth_serializer.OrganizationTypeSerializer(instance.type).data
|
||||
representation['permissions'] = PermissionSerializer(instance.permissions, many=True).data
|
||||
return representation
|
||||
|
||||
|
||||
class UserRelationSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = UserRelations
|
||||
fields = [
|
||||
'id',
|
||||
'user',
|
||||
'organization',
|
||||
'role',
|
||||
'permissions',
|
||||
]
|
||||
|
||||
def to_representation(self, instance):
|
||||
representation = super().to_representation(instance)
|
||||
if isinstance(instance, UserRelations):
|
||||
if instance.user:
|
||||
representation['user'] = auth_serializer.UserSerializer(instance.user).data
|
||||
if instance.organization:
|
||||
representation['organization'] = auth_serializer.OrganizationSerializer(instance.organization).data
|
||||
if instance.role:
|
||||
representation['role'] = RoleSerializer(instance.role).data
|
||||
if instance.permissions:
|
||||
representation['permissions'] = PermissionSerializer(instance.permissions, many=True).data
|
||||
|
||||
return representation
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
""" update user relation object """
|
||||
if validated_data.get('role'):
|
||||
instance.role = Role.objects.get(id=validated_data.get('role', instance.role))
|
||||
if validated_data.get('organization'):
|
||||
instance.organization = Organization.objects.get(id=validated_data.get(
|
||||
'organization', instance.organization
|
||||
))
|
||||
instance.save()
|
||||
instance.permissions.clear()
|
||||
instance.permissions.add(*(validated_data.get('permissions', instance.permissions)))
|
||||
return instance
|
||||
18
apps/authorization/api/v1/urls.py
Normal file
18
apps/authorization/api/v1/urls.py
Normal file
@@ -0,0 +1,18 @@
|
||||
from rest_framework.routers import DefaultRouter
|
||||
from django.urls import path, include
|
||||
from .api import (
|
||||
RoleViewSet,
|
||||
PermissionViewSet,
|
||||
UserRelationViewSet
|
||||
)
|
||||
|
||||
router = DefaultRouter() # set router
|
||||
|
||||
# register route to router
|
||||
router.register(r'role', RoleViewSet, basename='role')
|
||||
router.register(r'permission', PermissionViewSet, basename='permission')
|
||||
router.register(r'user-relations', UserRelationViewSet, basename='organization-role')
|
||||
|
||||
urlpatterns = [
|
||||
path('', include(router.urls))
|
||||
]
|
||||
0
apps/authorization/fixtures/.gitkeep
Normal file
0
apps/authorization/fixtures/.gitkeep
Normal file
0
apps/authorization/management/__init__.py
Normal file
0
apps/authorization/management/__init__.py
Normal file
0
apps/authorization/management/commands/__init__.py
Normal file
0
apps/authorization/management/commands/__init__.py
Normal file
1
apps/authorization/management/commands/command.py
Normal file
1
apps/authorization/management/commands/command.py
Normal file
@@ -0,0 +1 @@
|
||||
# Your custom management commands go here.
|
||||
18
apps/authorization/migrations/0004_alter_role_permissions.py
Normal file
18
apps/authorization/migrations/0004_alter_role_permissions.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-07 05:29
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authorization', '0003_remove_organizationrole_otp_status'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='role',
|
||||
name='permissions',
|
||||
field=models.ManyToManyField(null=True, to='authorization.permissions'),
|
||||
),
|
||||
]
|
||||
18
apps/authorization/migrations/0005_alter_role_permissions.py
Normal file
18
apps/authorization/migrations/0005_alter_role_permissions.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-07 05:30
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authorization', '0004_alter_role_permissions'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='role',
|
||||
name='permissions',
|
||||
field=models.ManyToManyField(to='authorization.permissions'),
|
||||
),
|
||||
]
|
||||
18
apps/authorization/migrations/0006_alter_role_role_name.py
Normal file
18
apps/authorization/migrations/0006_alter_role_role_name.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-07 08:03
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authorization', '0005_alter_role_permissions'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='role',
|
||||
name='role_name',
|
||||
field=models.CharField(max_length=50, unique=True),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-07 09:14
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authorization', '0006_alter_role_role_name'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='organizationrole',
|
||||
name='permissions',
|
||||
field=models.ManyToManyField(to='authorization.permissions'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,16 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-10 06:26
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authorization', '0007_organizationrole_permissions'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.DeleteModel(
|
||||
name='OrganizationRole',
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,40 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-10 08:51
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('authentication', '0008_remove_organization_type_organizationtype'),
|
||||
('authorization', '0008_delete_organizationrole'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='role',
|
||||
name='type',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='organization_role_type', to='authentication.organizationtype'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='UserRelations',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('create_date', models.DateTimeField(auto_now_add=True)),
|
||||
('modify_date', models.DateTimeField(auto_now=True)),
|
||||
('trash', models.BooleanField(default=False)),
|
||||
('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL)),
|
||||
('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL)),
|
||||
('organization', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='user_organization', to='authentication.organization')),
|
||||
('permissions', models.ManyToManyField(to='authorization.permissions')),
|
||||
('role', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_role', to='authorization.role')),
|
||||
('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_relation', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,37 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-17 06:01
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authorization', '0009_role_type_userrelations'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='permissions',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='permissions',
|
||||
name='modified_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='role',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='role',
|
||||
name='modified_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='userrelations',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='userrelations',
|
||||
name='modified_by',
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,43 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-17 06:24
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authorization', '0010_remove_permissions_created_by_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='permissions',
|
||||
name='created_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='permissions',
|
||||
name='modified_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='role',
|
||||
name='created_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='role',
|
||||
name='modified_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='userrelations',
|
||||
name='created_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='userrelations',
|
||||
name='modified_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,37 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-17 06:27
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authorization', '0011_permissions_created_by_permissions_modified_by_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='permissions',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='permissions',
|
||||
name='modified_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='role',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='role',
|
||||
name='modified_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='userrelations',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='userrelations',
|
||||
name='modified_by',
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,46 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-17 06:29
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('authorization', '0012_remove_permissions_created_by_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='permissions',
|
||||
name='created_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createddby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='permissions',
|
||||
name='modified_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='role',
|
||||
name='created_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createddby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='role',
|
||||
name='modified_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='userrelations',
|
||||
name='created_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createddby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='userrelations',
|
||||
name='modified_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,43 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-17 06:35
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authorization', '0013_permissions_created_by_permissions_modified_by_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='permissions',
|
||||
name='creator_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='permissions',
|
||||
name='modifier_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='role',
|
||||
name='creator_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='role',
|
||||
name='modifier_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='userrelations',
|
||||
name='creator_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='userrelations',
|
||||
name='modifier_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
]
|
||||
@@ -17,8 +17,14 @@ class Permissions(BaseModel):
|
||||
|
||||
|
||||
class Role(BaseModel):
|
||||
role_name = models.CharField(max_length=50)
|
||||
role_name = models.CharField(max_length=50, unique=True)
|
||||
description = models.TextField(max_length=500)
|
||||
type = models.ForeignKey(
|
||||
auth_models.OrganizationType,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="organization_role_type",
|
||||
null=True
|
||||
)
|
||||
permissions = models.ManyToManyField(Permissions)
|
||||
|
||||
def __str__(self):
|
||||
@@ -28,26 +34,28 @@ class Role(BaseModel):
|
||||
super(Role, self).save(*args, **kwargs)
|
||||
|
||||
|
||||
class OrganizationRole(BaseModel):
|
||||
class UserRelations(BaseModel):
|
||||
user = models.ForeignKey(
|
||||
auth_models.User,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='organization_user',
|
||||
related_name='user_relation',
|
||||
null=True
|
||||
)
|
||||
organization = models.ForeignKey(
|
||||
auth_models.Organization,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='organization'
|
||||
related_name='user_organization'
|
||||
)
|
||||
role = models.ForeignKey(
|
||||
Role,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='organization_role'
|
||||
related_name='user_role',
|
||||
null=True
|
||||
)
|
||||
permissions = models.ManyToManyField(Permissions)
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.organization.name}-{self.user.username}'
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
super(OrganizationRole, self).save(*args, **kwargs)
|
||||
super(UserRelations, self).save(*args, **kwargs)
|
||||
|
||||
0
apps/authorization/tests/test_common_services.py
Normal file
0
apps/authorization/tests/test_common_services.py
Normal file
5
apps/authorization/urls.py
Normal file
5
apps/authorization/urls.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from django.urls import path, include
|
||||
|
||||
urlpatterns = [
|
||||
path('api/v1/', include('apps.authorization.api.v1.urls'))
|
||||
]
|
||||
59
apps/core/middlewares.py
Normal file
59
apps/core/middlewares.py
Normal file
@@ -0,0 +1,59 @@
|
||||
from django.db import connection
|
||||
from django.conf import settings
|
||||
import os
|
||||
|
||||
|
||||
def terminal_width():
|
||||
"""
|
||||
Function to compute the terminal width.
|
||||
WARNING: This is not my code, but I've been using it forever and
|
||||
I don't remember where it came from.
|
||||
"""
|
||||
width = 0
|
||||
try:
|
||||
import struct, fcntl, termios
|
||||
s = struct.pack('HHHH', 0, 0, 0, 0)
|
||||
x = fcntl.ioctl(1, termios.TIOCGWINSZ, s)
|
||||
width = struct.unpack('HHHH', x)[1]
|
||||
except:
|
||||
pass
|
||||
if width <= 0:
|
||||
try:
|
||||
width = int(os.environ['COLUMNS'])
|
||||
except:
|
||||
pass
|
||||
if width <= 0:
|
||||
width = 80
|
||||
return width
|
||||
|
||||
|
||||
class SqlPrintingMiddleware(object):
|
||||
"""
|
||||
Middleware which prints out a list of all SQL queries done
|
||||
for each view that is processed. This is only useful for debugging.
|
||||
"""
|
||||
|
||||
def __init__(self, get_response):
|
||||
# print("heloo")
|
||||
self.get_response = get_response
|
||||
|
||||
def __call__(self, request):
|
||||
return self.process_response(request=request, response=self.get_response(request))
|
||||
|
||||
def process_response(self, request, response): # noqa
|
||||
indentation = 2
|
||||
if len(connection.queries) > 0 and settings.DEBUG:
|
||||
width = terminal_width()
|
||||
total_time = 0.0
|
||||
for query in connection.queries:
|
||||
nice_sql = query['sql'].replace('"', '').replace(',', ', ')
|
||||
sql = "\033[1;31m[%s]\033[0m %s" % (query['time'], nice_sql)
|
||||
total_time = total_time + float(query['time'])
|
||||
while len(sql) > width - indentation:
|
||||
print("%s%s" % (" " * indentation, sql[:width - indentation]))
|
||||
sql = sql[width - indentation:]
|
||||
print("%s%s\n" % (" " * indentation, sql))
|
||||
replace_tuple = (" " * indentation, str(total_time))
|
||||
print("%s\033[1;32m[TOTAL TIME: %s seconds]\033[0m" % replace_tuple)
|
||||
print(response)
|
||||
return response
|
||||
@@ -0,0 +1,21 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-17 06:01
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='mobiletest',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='mobiletest',
|
||||
name='modified_by',
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,23 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-17 06:24
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0002_remove_mobiletest_created_by_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='mobiletest',
|
||||
name='created_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='mobiletest',
|
||||
name='modified_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,21 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-17 06:27
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0003_mobiletest_created_by_mobiletest_modified_by'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='mobiletest',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='mobiletest',
|
||||
name='modified_by',
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,26 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-17 06:29
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('core', '0004_remove_mobiletest_created_by_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='mobiletest',
|
||||
name='created_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createddby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='mobiletest',
|
||||
name='modified_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,23 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-17 06:35
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0005_mobiletest_created_by_mobiletest_modified_by'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='mobiletest',
|
||||
name='creator_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='mobiletest',
|
||||
name='modifier_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
]
|
||||
@@ -1,5 +1,6 @@
|
||||
from django.db import models
|
||||
from django.conf import settings
|
||||
from crum import get_current_user
|
||||
|
||||
|
||||
class BaseModel(models.Model):
|
||||
@@ -7,8 +8,8 @@ class BaseModel(models.Model):
|
||||
modify_date = models.DateTimeField(auto_now=True)
|
||||
created_by = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL,
|
||||
related_name="%(class)s_createdby",
|
||||
on_delete=models.CASCADE,
|
||||
related_name="%(class)s_createddby",
|
||||
null=True,
|
||||
blank=True,
|
||||
)
|
||||
@@ -19,11 +20,22 @@ class BaseModel(models.Model):
|
||||
null=True,
|
||||
blank=True,
|
||||
)
|
||||
creator_info = models.CharField(max_length=100, null=True)
|
||||
modifier_info = models.CharField(max_length=100, null=True)
|
||||
trash = models.BooleanField(default=False)
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
user = get_current_user() # get user object
|
||||
self.modified_by = user
|
||||
if not self.creator_info:
|
||||
self.created_by = user
|
||||
self.creator_info = user.first_name + ' ' + user.last_name + '-' + user.national_code
|
||||
self.modifier_info = user.first_name + ' ' + user.last_name + '-' + user.national_code
|
||||
super(BaseModel, self).save(*args, **kwargs)
|
||||
|
||||
|
||||
class MobileTest(BaseModel):
|
||||
latitude = models.DecimalField(max_digits=22, decimal_places=16)
|
||||
|
||||
48
apps/core/permissions.py
Normal file
48
apps/core/permissions.py
Normal file
@@ -0,0 +1,48 @@
|
||||
from rest_framework.permissions import BasePermissionMetaclass
|
||||
from apps.authorization import models as authorize_models
|
||||
import itertools
|
||||
import typing
|
||||
|
||||
|
||||
class BasePermission(metaclass=BasePermissionMetaclass):
|
||||
"""
|
||||
A base class from which all permission classes should inherit.
|
||||
"""
|
||||
|
||||
def get_user_permissions(self, request, view) -> typing.Dict: # noqa
|
||||
"""
|
||||
get permissions by role and user specified permissions
|
||||
combined permissions and returns a list
|
||||
"""
|
||||
organization_type = []
|
||||
permissions_info = {}
|
||||
relations = request.user.user_relation.select_related()
|
||||
for relation in relations:
|
||||
role_permissions = list(itertools.chain(*[
|
||||
list(item.values()) for item in
|
||||
list(relation.role.permissions.prefetch_related().values('name'))
|
||||
]
|
||||
))
|
||||
user_permissions = list(itertools.chain(*[
|
||||
list(item.values()) for item in
|
||||
list(relation.permissions.prefetch_related().values('name'))])
|
||||
)
|
||||
result = list(set(role_permissions + user_permissions))
|
||||
organization_type.append(relation.organization.type.key)
|
||||
permissions_info['organization_type'] = organization_type
|
||||
permissions_info['permissions'] = result
|
||||
print(result, permissions_info)
|
||||
return permissions_info
|
||||
|
||||
def has_permission(self, request, view): # noqa
|
||||
"""
|
||||
Return `True` if permission is granted, `False` otherwise.
|
||||
"""
|
||||
|
||||
return True
|
||||
|
||||
def has_object_permission(self, request, view, obj): # noqa
|
||||
"""
|
||||
Return `True` if permission is granted, `False` otherwise.
|
||||
"""
|
||||
return True
|
||||
16
apps/core/swagger.py
Normal file
16
apps/core/swagger.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from rest_framework import permissions
|
||||
from drf_yasg.views import get_schema_view
|
||||
from drf_yasg import openapi
|
||||
|
||||
schema_view = get_schema_view(
|
||||
openapi.Info(
|
||||
title="RasadDam Api",
|
||||
default_version='v1',
|
||||
description="All Apis",
|
||||
terms_of_service="https://www.google.com/policies/terms/",
|
||||
contact=openapi.Contact(email="contact@myapi.local"),
|
||||
license=openapi.License(name="BSD License"),
|
||||
),
|
||||
public=True,
|
||||
permission_classes=[permissions.BasePermission, permissions.IsAuthenticated]
|
||||
)
|
||||
@@ -0,0 +1,32 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-13 06:31
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authentication', '0010_organization_company_code_and_more'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('herd', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='herd',
|
||||
name='city',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='herd_city', to='authentication.city'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='herd',
|
||||
name='owner',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='herd', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='herd',
|
||||
name='province',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='herd_province', to='authentication.province'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,21 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-17 06:01
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('herd', '0002_herd_city_herd_owner_herd_province'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='herd',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='herd',
|
||||
name='modified_by',
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,23 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-17 06:24
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('herd', '0003_remove_herd_created_by_remove_herd_modified_by'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='herd',
|
||||
name='created_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='herd',
|
||||
name='modified_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,21 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-17 06:27
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('herd', '0004_herd_created_by_herd_modified_by'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='herd',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='herd',
|
||||
name='modified_by',
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,26 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-17 06:29
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('herd', '0005_remove_herd_created_by_remove_herd_modified_by'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='herd',
|
||||
name='created_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createddby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='herd',
|
||||
name='modified_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,23 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-17 06:35
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('herd', '0006_herd_created_by_herd_modified_by'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='herd',
|
||||
name='creator_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='herd',
|
||||
name='modifier_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,40 @@
|
||||
# Generated by Django 5.0 on 2025-05-19 08:14
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authentication', '0017_bankaccountinformation_creator_info_and_more'),
|
||||
('herd', '0007_herd_creator_info_herd_modifier_info'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='herd',
|
||||
name='cooperative',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='herd', to='authentication.organization'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='herd',
|
||||
name='heavy_livestock_number',
|
||||
field=models.BigIntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='herd',
|
||||
name='heavy_livestock_quota',
|
||||
field=models.BigIntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='herd',
|
||||
name='light_livestock_number',
|
||||
field=models.BigIntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='herd',
|
||||
name='light_livestock_quota',
|
||||
field=models.BigIntegerField(default=0),
|
||||
),
|
||||
]
|
||||
@@ -4,9 +4,37 @@ from django.db import models
|
||||
|
||||
|
||||
class Herd(BaseModel):
|
||||
owner = models.ForeignKey(
|
||||
auth_models.User,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='herd',
|
||||
null=True
|
||||
)
|
||||
cooperative = models.ForeignKey(
|
||||
auth_models.Organization,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='herd',
|
||||
null=True
|
||||
)
|
||||
name = models.CharField(max_length=50)
|
||||
photo = models.CharField(max_length=50, null=True)
|
||||
code = models.CharField(max_length=20)
|
||||
heavy_livestock_number = models.BigIntegerField(default=0)
|
||||
light_livestock_number = models.BigIntegerField(default=0)
|
||||
heavy_livestock_quota = models.BigIntegerField(default=0)
|
||||
light_livestock_quota = models.BigIntegerField(default=0)
|
||||
province = models.ForeignKey(
|
||||
auth_models.Province,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='herd_province',
|
||||
null=True
|
||||
)
|
||||
city = models.ForeignKey(
|
||||
auth_models.City,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='herd_city',
|
||||
null=True
|
||||
)
|
||||
postal = models.CharField(
|
||||
max_length=10,
|
||||
help_text="herd postal code", null=True
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
# Your services go here
|
||||
|
||||
|
||||
|
||||
@@ -1 +1,8 @@
|
||||
# Your urls go here
|
||||
|
||||
from django.urls import path, include
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path('web/', include('apps.herd.web.api.v1.urls'))
|
||||
]
|
||||
|
||||
87
apps/herd/web/api/v1/api.py
Normal file
87
apps/herd/web/api/v1/api.py
Normal file
@@ -0,0 +1,87 @@
|
||||
from apps.herd.web.api.v1.serializers import HerdSerializer
|
||||
from apps.authentication.api.v1.api import UserViewSet
|
||||
from rest_framework.exceptions import APIException
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.decorators import action
|
||||
from common.tools import CustomOperations
|
||||
from rest_framework import viewsets
|
||||
from apps.herd.models import Herd
|
||||
from django.db import transaction
|
||||
from rest_framework import status
|
||||
|
||||
|
||||
class HerdViewSet(viewsets.ModelViewSet):
|
||||
""" Herd ViewSet """
|
||||
queryset = Herd.objects.all()
|
||||
serializer_class = HerdSerializer
|
||||
|
||||
@transaction.atomic
|
||||
def create(self, request, *args, **kwargs):
|
||||
""" create herd with user """
|
||||
if 'user' in request.data.keys():
|
||||
# create user if owner of herd is not exist
|
||||
user = CustomOperations().custom_create(
|
||||
request=request,
|
||||
view=UserViewSet(),
|
||||
data_key='user'
|
||||
)
|
||||
owner = user['id']
|
||||
request.data.update({'owner': owner})
|
||||
|
||||
serializer = self.serializer_class(data=request.data)
|
||||
if serializer.is_valid():
|
||||
serializer.save()
|
||||
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
||||
else:
|
||||
return Response(serializer.errors, status=status.HTTP_403_FORBIDDEN)
|
||||
|
||||
@action(
|
||||
methods=['get'],
|
||||
detail=False,
|
||||
url_name='my_herds',
|
||||
url_path='my_herds',
|
||||
name='my_herds'
|
||||
)
|
||||
@transaction.atomic
|
||||
def my_herds(self, request):
|
||||
""" get current user herds """
|
||||
serializer = self.serializer_class(self.queryset.filter(owner=request.user.id), many=True)
|
||||
if serializer.data:
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
else:
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
@action(
|
||||
methods=['post'],
|
||||
detail=True,
|
||||
url_path='trash',
|
||||
url_name='trash',
|
||||
name='trash'
|
||||
)
|
||||
@transaction.atomic
|
||||
def trash(self, request, pk=None):
|
||||
""" Sent herd to trash """
|
||||
try:
|
||||
herd = self.queryset.get(id=pk)
|
||||
herd.trash = True
|
||||
herd.save()
|
||||
return Response(status=status.HTTP_200_OK)
|
||||
except APIException as e:
|
||||
return Response(e, status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
@action(
|
||||
methods=['post'],
|
||||
detail=True,
|
||||
url_path='delete',
|
||||
url_name='delete',
|
||||
name='delete'
|
||||
)
|
||||
@transaction.atomic
|
||||
def delete(self, request, pk=None):
|
||||
""" full delete of herd """
|
||||
try:
|
||||
herd = self.queryset.get(id=pk)
|
||||
herd.delete()
|
||||
return Response(status=status.HTTP_200_OK)
|
||||
except APIException as e:
|
||||
return Response(e, status=status.HTTP_204_NO_CONTENT)
|
||||
@@ -0,0 +1,27 @@
|
||||
from apps.authentication.api.v1.serializers.serializer import (
|
||||
UserSerializer,
|
||||
OrganizationSerializer,
|
||||
ProvinceSerializer,
|
||||
CitySerializer
|
||||
)
|
||||
from rest_framework import serializers
|
||||
from apps.herd.models import Herd
|
||||
|
||||
|
||||
class HerdSerializer(serializers.ModelSerializer):
|
||||
""" Herd Serializer """
|
||||
class Meta:
|
||||
model = Herd
|
||||
fields = '__all__'
|
||||
|
||||
def to_representation(self, instance):
|
||||
""" Customize serializer output """
|
||||
representation = super().to_representation(instance)
|
||||
if isinstance(instance, Herd):
|
||||
representation['owner'] = UserSerializer(instance.owner).data
|
||||
representation['cooperative'] = OrganizationSerializer(instance.cooperative).data
|
||||
representation['province'] = ProvinceSerializer(instance.province).data
|
||||
representation['city'] = CitySerializer(instance.city).data
|
||||
representation['contractor'] = OrganizationSerializer(instance.contractor).data
|
||||
|
||||
return representation
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
from django.urls import path, include
|
||||
from rest_framework import routers
|
||||
from .api import HerdViewSet
|
||||
|
||||
router = routers.DefaultRouter()
|
||||
router.register('herd', HerdViewSet, basename='herd')
|
||||
|
||||
urlpatterns = [
|
||||
path('api/v1/', include(router.urls))
|
||||
]
|
||||
@@ -0,0 +1,32 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-12 11:35
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('livestock', '0002_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='livestock',
|
||||
name='type',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='livestock',
|
||||
name='age_by_day',
|
||||
field=models.IntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='livestock',
|
||||
name='age_by_month',
|
||||
field=models.IntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='livestock',
|
||||
name='age_by_year',
|
||||
field=models.IntegerField(default=0),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,70 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-12 12:17
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('livestock', '0003_remove_livestock_type_livestock_age_by_day_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='livestock',
|
||||
name='species',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='livestock',
|
||||
name='weight_type',
|
||||
field=models.CharField(choices=[('L', 'Light'), ('H', 'Heavy')], default='L', max_length=1),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='LiveStockUseType',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('create_date', models.DateTimeField(auto_now_add=True)),
|
||||
('modify_date', models.DateTimeField(auto_now=True)),
|
||||
('trash', models.BooleanField(default=False)),
|
||||
('name', models.CharField(max_length=50)),
|
||||
('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL)),
|
||||
('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='LiveStockType',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('create_date', models.DateTimeField(auto_now_add=True)),
|
||||
('modify_date', models.DateTimeField(auto_now=True)),
|
||||
('trash', models.BooleanField(default=False)),
|
||||
('name', models.CharField(max_length=50)),
|
||||
('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL)),
|
||||
('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='LiveStockSpecies',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('create_date', models.DateTimeField(auto_now_add=True)),
|
||||
('modify_date', models.DateTimeField(auto_now=True)),
|
||||
('trash', models.BooleanField(default=False)),
|
||||
('name', models.CharField(max_length=50)),
|
||||
('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL)),
|
||||
('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,29 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-12 12:28
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('livestock', '0004_remove_livestock_species_livestock_weight_type_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='livestock',
|
||||
name='species',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='livestock_species', to='livestock.livestockspecies'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='livestock',
|
||||
name='type',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='livestock_type', to='livestock.livestocktype'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='livestock',
|
||||
name='use_type',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='livestock_use_type', to='livestock.livestockusetype'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,45 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-17 06:01
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('livestock', '0005_livestock_species_livestock_type_livestock_use_type'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='livestock',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='livestock',
|
||||
name='modified_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='livestockspecies',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='livestockspecies',
|
||||
name='modified_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='livestocktype',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='livestocktype',
|
||||
name='modified_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='livestockusetype',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='livestockusetype',
|
||||
name='modified_by',
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,53 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-17 06:24
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('livestock', '0006_remove_livestock_created_by_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='livestock',
|
||||
name='created_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='livestock',
|
||||
name='modified_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='livestockspecies',
|
||||
name='created_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='livestockspecies',
|
||||
name='modified_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='livestocktype',
|
||||
name='created_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='livestocktype',
|
||||
name='modified_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='livestockusetype',
|
||||
name='created_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='livestockusetype',
|
||||
name='modified_by',
|
||||
field=models.CharField(max_length=50, null=True),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,45 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-17 06:27
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('livestock', '0007_livestock_created_by_livestock_modified_by_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='livestock',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='livestock',
|
||||
name='modified_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='livestockspecies',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='livestockspecies',
|
||||
name='modified_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='livestocktype',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='livestocktype',
|
||||
name='modified_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='livestockusetype',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='livestockusetype',
|
||||
name='modified_by',
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,56 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-17 06:29
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('livestock', '0008_remove_livestock_created_by_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='livestock',
|
||||
name='created_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createddby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='livestock',
|
||||
name='modified_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='livestockspecies',
|
||||
name='created_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createddby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='livestockspecies',
|
||||
name='modified_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='livestocktype',
|
||||
name='created_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createddby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='livestocktype',
|
||||
name='modified_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='livestockusetype',
|
||||
name='created_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createddby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='livestockusetype',
|
||||
name='modified_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,53 @@
|
||||
# Generated by Django 4.2.20 on 2025-05-17 06:35
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('livestock', '0009_livestock_created_by_livestock_modified_by_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='livestock',
|
||||
name='creator_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='livestock',
|
||||
name='modifier_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='livestockspecies',
|
||||
name='creator_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='livestockspecies',
|
||||
name='modifier_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='livestocktype',
|
||||
name='creator_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='livestocktype',
|
||||
name='modifier_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='livestockusetype',
|
||||
name='creator_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='livestockusetype',
|
||||
name='modifier_info',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,25 @@
|
||||
# Generated by Django 5.0 on 2025-05-24 09:12
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('livestock', '0010_livestock_creator_info_livestock_modifier_info_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='livestock',
|
||||
name='age_by_day',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='livestock',
|
||||
name='age_by_month',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='livestock',
|
||||
name='age_by_year',
|
||||
),
|
||||
]
|
||||
@@ -4,6 +4,39 @@ from apps.tag import models as tag_models
|
||||
from django.db import models
|
||||
|
||||
|
||||
class LiveStockSpecies(BaseModel): # noqa
|
||||
""" species of live stocks like Kurdi, Luri, etc """ # noqa
|
||||
name = models.CharField(max_length=50)
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.name}'
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
super(LiveStockSpecies, self).save(*args, **kwargs)
|
||||
|
||||
|
||||
class LiveStockType(BaseModel): # noqa
|
||||
""" types like sheep, cow, camel, etc """
|
||||
name = models.CharField(max_length=50)
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.name}'
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
super(LiveStockType, self).save(*args, **kwargs)
|
||||
|
||||
|
||||
class LiveStockUseType(BaseModel):
|
||||
""" use types like Beef, Milky, etc """
|
||||
name = models.CharField(max_length=50)
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.name}'
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
super(LiveStockUseType, self).save(*args, **kwargs)
|
||||
|
||||
|
||||
class LiveStock(BaseModel):
|
||||
herd = models.ForeignKey(
|
||||
herd_models.Herd,
|
||||
@@ -17,15 +50,29 @@ class LiveStock(BaseModel):
|
||||
related_name='livestock_tag',
|
||||
null=True
|
||||
)
|
||||
types = (
|
||||
type = models.ForeignKey(
|
||||
LiveStockType,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='livestock_type',
|
||||
null=True
|
||||
)
|
||||
use_type = models.ForeignKey(
|
||||
LiveStockUseType,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='livestock_use_type',
|
||||
null=True
|
||||
)
|
||||
weight_types = (
|
||||
('L', 'Light'),
|
||||
('H', 'Heavy')
|
||||
)
|
||||
type = models.CharField(max_length=1, choices=types)
|
||||
species_type = (
|
||||
()
|
||||
weight_type = models.CharField(max_length=1, choices=weight_types, default='L')
|
||||
species = models.ForeignKey(
|
||||
LiveStockSpecies,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='livestock_species',
|
||||
null=True,
|
||||
)
|
||||
species = models.CharField(max_length=1, choices=species_type)
|
||||
birthdate = models.DateTimeField(null=True)
|
||||
gender_type = (
|
||||
(1, 'male'),
|
||||
@@ -34,7 +81,7 @@ class LiveStock(BaseModel):
|
||||
gender = models.IntegerField(choices=gender_type, default=1)
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.get_species_display()}-{self.get_type_display()}'
|
||||
return f'{self.type.name}-{self.species.name}'
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
super(LiveStock, self).save(*args, **kwargs)
|
||||
|
||||
@@ -1,25 +1,145 @@
|
||||
from rest_framework import permissions
|
||||
from apps.core import permissions
|
||||
|
||||
|
||||
# example Code
|
||||
class AuthorAllStaffAllButEditOrReadOnly(permissions.BasePermission):
|
||||
edit_methods = ("PUT", "PATCH")
|
||||
class LiveStockCreatePermission(permissions.BasePermission):
|
||||
""" permission to create livestock """
|
||||
|
||||
def has_permission(self, request, view):
|
||||
if request.user.is_authenticated:
|
||||
user_level_info = self.get_user_permissions(request, view)
|
||||
if 'live_stock_create' in user_level_info['permissions']:
|
||||
return True
|
||||
|
||||
def has_object_permission(self, request, view, obj):
|
||||
if request.user.is_superuser:
|
||||
|
||||
class LiveStockUpdatePermission(permissions.BasePermission):
|
||||
""" permission to update livestock """
|
||||
|
||||
def has_permission(self, request, view):
|
||||
user_level_info = self.get_user_permissions(request, view)
|
||||
if 'live_stock_update' in user_level_info['permissions']:
|
||||
return True
|
||||
|
||||
if request.method in permissions.SAFE_METHODS:
|
||||
|
||||
class LiveStockTrashPermission(permissions.BasePermission):
|
||||
""" permission to trash livestock """
|
||||
|
||||
def has_permission(self, request, view):
|
||||
user_level_info = self.get_user_permissions(request, view)
|
||||
if 'live_stock_trash' in user_level_info['permissions']:
|
||||
return True
|
||||
|
||||
if obj.author == request.user:
|
||||
|
||||
class LiveStockDeletePermission(permissions.BasePermission):
|
||||
""" permission to Delete livestock """
|
||||
|
||||
def has_permission(self, request, view):
|
||||
user_level_info = self.get_user_permissions(request, view)
|
||||
if 'live_stock_delete' in user_level_info['permissions']:
|
||||
return True
|
||||
|
||||
if request.user.is_staff and request.method not in self.edit_methods:
|
||||
|
||||
class StockTypeCreatePermission(permissions.BasePermission):
|
||||
""" permission to create livestock type """
|
||||
|
||||
def has_permission(self, request, view):
|
||||
user_level_info = self.get_user_permissions(request, view)
|
||||
if 'stock_type_create' in user_level_info['permissions']:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
class StockTypeUpdatePermission(permissions.BasePermission):
|
||||
""" permission to update livestock type """
|
||||
|
||||
def has_permission(self, request, view):
|
||||
user_level_info = self.get_user_permissions(request, view)
|
||||
if 'stock_type_update' in user_level_info['permissions']:
|
||||
return True
|
||||
|
||||
|
||||
class StockTypeTrashPermission(permissions.BasePermission):
|
||||
""" permission to trash livestock type """
|
||||
|
||||
def has_permission(self, request, view):
|
||||
user_level_info = self.get_user_permissions(request, view)
|
||||
if 'stock_type_trash' in user_level_info['permissions']:
|
||||
return True
|
||||
|
||||
|
||||
class StockTypeDeletePermission(permissions.BasePermission):
|
||||
""" permission to delete livestock type """
|
||||
|
||||
def has_permission(self, request, view):
|
||||
user_level_info = self.get_user_permissions(request, view)
|
||||
if 'stock_type_delete' in user_level_info['permissions']:
|
||||
return True
|
||||
|
||||
|
||||
class StockUseTypeCreatePermission(permissions.BasePermission):
|
||||
""" permission to create livestock use type """
|
||||
|
||||
def has_permission(self, request, view):
|
||||
user_level_info = self.get_user_permissions(request, view)
|
||||
if 'stock_use_type_create' in user_level_info['permissions']:
|
||||
return True
|
||||
|
||||
|
||||
class StockUseTypeUpdatePermission(permissions.BasePermission):
|
||||
""" permission to update livestock use type """
|
||||
|
||||
def has_permission(self, request, view):
|
||||
user_level_info = self.get_user_permissions(request, view)
|
||||
if 'stock_use_type_update' in user_level_info['permissions']:
|
||||
return True
|
||||
|
||||
|
||||
class StockUseTypeTrashPermission(permissions.BasePermission):
|
||||
""" permission to trash livestock use type """
|
||||
|
||||
def has_permission(self, request, view):
|
||||
user_level_info = self.get_user_permissions(request, view)
|
||||
if 'stock_use_type_trash' in user_level_info['permissions']:
|
||||
return True
|
||||
|
||||
|
||||
class StockUseTypeDeletePermission(permissions.BasePermission):
|
||||
""" permission to delete livestock use type """
|
||||
|
||||
def has_permission(self, request, view):
|
||||
user_level_info = self.get_user_permissions(request, view)
|
||||
if 'stock_use_type_delete' in user_level_info['permissions']:
|
||||
return True
|
||||
|
||||
|
||||
class StockSpeciesCreatePermission(permissions.BasePermission):
|
||||
""" permission to create livestock species """
|
||||
|
||||
def has_permission(self, request, view):
|
||||
user_level_info = self.get_user_permissions(request, view)
|
||||
if 'stock_species_create' in user_level_info['permissions']:
|
||||
return True
|
||||
|
||||
|
||||
class StockSpeciesUpdatePermission(permissions.BasePermission):
|
||||
""" permission to update livestock species """
|
||||
|
||||
def has_permission(self, request, view):
|
||||
user_level_info = self.get_user_permissions(request, view)
|
||||
if 'stock_species_update' in user_level_info['permissions']:
|
||||
return True
|
||||
|
||||
|
||||
class StockSpeciesTrashPermission(permissions.BasePermission):
|
||||
""" permission to trash livestock species """
|
||||
|
||||
def has_permission(self, request, view):
|
||||
user_level_info = self.get_user_permissions(request, view)
|
||||
if 'stock_species_trash' in user_level_info['permissions']:
|
||||
return True
|
||||
|
||||
|
||||
class StockSpeciesDeletePermission(permissions.BasePermission):
|
||||
""" permission to delete livestock species """
|
||||
|
||||
def has_permission(self, request, view):
|
||||
user_level_info = self.get_user_permissions(request, view)
|
||||
if 'stock_species_delete' in user_level_info['permissions']:
|
||||
return True
|
||||
|
||||
@@ -1 +1,8 @@
|
||||
# Your urls go here
|
||||
from django.urls import path, include
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path('web/api/', include('apps.livestock.web.api.v1.urls')),
|
||||
# path('app/api/', include('apps.livestock.mobile.api.v1.urls')),
|
||||
# path('pos/api/', include('apps.livestock.pos.api.v1.urls'))
|
||||
]
|
||||
166
apps/livestock/web/api/v1/api.py
Normal file
166
apps/livestock/web/api/v1/api.py
Normal file
@@ -0,0 +1,166 @@
|
||||
from rest_framework import viewsets
|
||||
from apps.livestock import models as livestock_models
|
||||
from . import serializers as livestock_serializers
|
||||
from rest_framework.exceptions import APIException
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.response import Response
|
||||
from django.db import transaction
|
||||
from rest_framework import status
|
||||
|
||||
|
||||
def trash(queryset, pk):
|
||||
""" sent object to trash """
|
||||
obj = queryset.get(id=pk)
|
||||
obj.trash = True
|
||||
obj.save()
|
||||
|
||||
|
||||
def delete(queryset, pk):
|
||||
""" full delete object """
|
||||
obj = queryset.get(id=pk)
|
||||
obj.delete()
|
||||
|
||||
|
||||
class LiveStockViewSet(viewsets.ModelViewSet):
|
||||
queryset = livestock_models.LiveStock.objects.all()
|
||||
serializer_class = livestock_serializers.LiveStockSerializer
|
||||
|
||||
@action(
|
||||
methods=['put'],
|
||||
detail=True,
|
||||
url_path='trash',
|
||||
url_name='trash',
|
||||
name='trash',
|
||||
)
|
||||
@transaction.atomic
|
||||
def trash(self, request, pk=None):
|
||||
""" Sent livestock to trash """
|
||||
try:
|
||||
trash(self.queryset, pk)
|
||||
except APIException as e:
|
||||
return Response(e, status.HTTP_204_NO_CONTENT)
|
||||
|
||||
@action(
|
||||
methods=['post'],
|
||||
detail=True,
|
||||
url_name='delete',
|
||||
url_path='delete',
|
||||
name='delete'
|
||||
)
|
||||
@transaction.atomic
|
||||
def delete(self, request, pk=None):
|
||||
""" Full delete of livestock object """
|
||||
try:
|
||||
delete(self.queryset, pk)
|
||||
return Response(status=status.HTTP_200_OK)
|
||||
except APIException as e:
|
||||
return Response(e, status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
|
||||
class LiveStockTypeViewSet(viewsets.ModelViewSet):
|
||||
queryset = livestock_models.LiveStockType.objects.all()
|
||||
serializer_class = livestock_serializers.LiveStockTypeSerializer
|
||||
|
||||
@action(
|
||||
methods=['put'],
|
||||
detail=True,
|
||||
url_path='trash',
|
||||
url_name='trash',
|
||||
name='trash',
|
||||
)
|
||||
@transaction.atomic
|
||||
def trash(self, request, pk=None):
|
||||
""" Sent livestock type to trash """
|
||||
try:
|
||||
trash(self.queryset, pk)
|
||||
except APIException as e:
|
||||
return Response(e, status.HTTP_204_NO_CONTENT)
|
||||
|
||||
@action(
|
||||
methods=['post'],
|
||||
detail=True,
|
||||
url_name='delete',
|
||||
url_path='delete',
|
||||
name='delete'
|
||||
)
|
||||
@transaction.atomic
|
||||
def delete(self, request, pk=None):
|
||||
""" Full delete of livestock type object """
|
||||
try:
|
||||
delete(self.queryset, pk)
|
||||
return Response(status=status.HTTP_200_OK)
|
||||
except APIException as e:
|
||||
return Response(e, status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
|
||||
class LiveStockUseTypeViewSet(viewsets.ModelViewSet):
|
||||
queryset = livestock_models.LiveStockUseType.objects.all()
|
||||
serializer_class = livestock_serializers.LiveStockUseTypeSerializer
|
||||
|
||||
@action(
|
||||
methods=['put'],
|
||||
detail=True,
|
||||
url_path='trash',
|
||||
url_name='trash',
|
||||
name='trash',
|
||||
)
|
||||
@transaction.atomic
|
||||
def trash(self, request, pk=None):
|
||||
""" Sent livestock use type to trash """
|
||||
try:
|
||||
trash(self.queryset, pk)
|
||||
except APIException as e:
|
||||
return Response(e, status.HTTP_204_NO_CONTENT)
|
||||
|
||||
@action(
|
||||
methods=['post'],
|
||||
detail=True,
|
||||
url_name='delete',
|
||||
url_path='delete',
|
||||
name='delete'
|
||||
)
|
||||
@transaction.atomic
|
||||
def delete(self, request, pk=None):
|
||||
""" Full delete of livestock use type object """
|
||||
try:
|
||||
delete(self.queryset, pk)
|
||||
return Response(status=status.HTTP_200_OK)
|
||||
except APIException as e:
|
||||
return Response(e, status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
|
||||
class LiveStockSpeciesViewSet(viewsets.ModelViewSet):
|
||||
queryset = livestock_models.LiveStockSpecies.objects.all()
|
||||
serializer_class = livestock_serializers.LiveStockSpeciesSerializer
|
||||
|
||||
@action(
|
||||
methods=['put'],
|
||||
detail=True,
|
||||
url_path='trash',
|
||||
url_name='trash',
|
||||
name='trash',
|
||||
)
|
||||
@transaction.atomic
|
||||
def trash(self, request, pk=None):
|
||||
""" Sent species to trash """
|
||||
try:
|
||||
trash(self.queryset, pk)
|
||||
return Response(status=status.HTTP_200_OK)
|
||||
except APIException as e:
|
||||
return Response
|
||||
|
||||
@action(
|
||||
methods=['post'],
|
||||
detail=True,
|
||||
url_name='delete',
|
||||
url_path='delete',
|
||||
name='delete'
|
||||
)
|
||||
@transaction.atomic
|
||||
def delete(self, request, pk=None):
|
||||
""" Full delete of species object """
|
||||
try:
|
||||
delete(self.queryset, pk)
|
||||
return Response(status=status.HTTP_200_OK)
|
||||
except APIException as e:
|
||||
return Response(e, status=status.HTTP_204_NO_CONTENT)
|
||||
@@ -0,0 +1,62 @@
|
||||
from rest_framework import serializers
|
||||
from apps.livestock import models as livestock_models
|
||||
from apps.herd.web.api.v1.serializers import HerdSerializer
|
||||
from apps.tag.web.api.v1.serializers import TagSerializer
|
||||
|
||||
|
||||
class LiveStockTypeSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = livestock_models.LiveStockType
|
||||
fields = [
|
||||
'id',
|
||||
'name'
|
||||
]
|
||||
|
||||
|
||||
class LiveStockUseTypeSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = livestock_models.LiveStockUseType
|
||||
fields = [
|
||||
'id',
|
||||
'name'
|
||||
]
|
||||
|
||||
|
||||
class LiveStockSpeciesSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = livestock_models.LiveStockSpecies
|
||||
fields = [
|
||||
'id',
|
||||
'name'
|
||||
]
|
||||
|
||||
|
||||
class LiveStockSerializer(serializers.ModelSerializer):
|
||||
""" livestock serializer """
|
||||
|
||||
class Meta:
|
||||
model = livestock_models.LiveStock
|
||||
fields = [
|
||||
'id',
|
||||
'herd',
|
||||
'tag',
|
||||
'type',
|
||||
'use_type',
|
||||
'weight_type',
|
||||
'species',
|
||||
'birthdate',
|
||||
'gender',
|
||||
]
|
||||
depth = 1
|
||||
|
||||
def to_representation(self, instance):
|
||||
""" Customize output of serializer """
|
||||
representation = super().to_representation(instance)
|
||||
if isinstance(instance, livestock_models.LiveStock):
|
||||
representation['herd'] = HerdSerializer(instance.herd).data
|
||||
representation['tag'] = TagSerializer(instance.tag).data
|
||||
representation['type'] = LiveStockTypeSerializer(instance.type).data
|
||||
representation['use_type'] = LiveStockUseTypeSerializer(instance.use_type).data
|
||||
representation['species'] = LiveStockSpeciesSerializer(instance.species).data
|
||||
|
||||
return representation
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
from django.urls import path, include
|
||||
from rest_framework.routers import DefaultRouter
|
||||
from .api import (
|
||||
LiveStockViewSet,
|
||||
LiveStockTypeViewSet,
|
||||
LiveStockSpeciesViewSet,
|
||||
LiveStockUseTypeViewSet
|
||||
)
|
||||
|
||||
router = DefaultRouter()
|
||||
router.register(r'livestock', LiveStockViewSet, basename='livestock')
|
||||
router.register(r'livestock_type', LiveStockTypeViewSet, basename='livestock_type')
|
||||
router.register(r'livestock_use_type', LiveStockUseTypeViewSet, basename='livestock_use_type')
|
||||
router.register(r'livestock_species', LiveStockSpeciesViewSet, basename='livestock_species')
|
||||
|
||||
urlpatterns = [
|
||||
path('v1/', include(router.urls))
|
||||
]
|
||||
|
||||
0
apps/log/__init__.py
Normal file
0
apps/log/__init__.py
Normal file
3
apps/log/admin.py
Normal file
3
apps/log/admin.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
6
apps/log/apps.py
Normal file
6
apps/log/apps.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class LogConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'apps.log'
|
||||
56
apps/log/middlewares.py
Normal file
56
apps/log/middlewares.py
Normal file
@@ -0,0 +1,56 @@
|
||||
import time
|
||||
from .models import Log
|
||||
from tinydb import TinyDB, Query
|
||||
from django.core import serializers
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class SaveLog:
|
||||
def __init__(self, get_response):
|
||||
self.get_response = get_response
|
||||
|
||||
# Filter to log all request to url's that start with any of the strings below.
|
||||
# With example below:
|
||||
# /example/test/ will be logged.
|
||||
# /other/ will not be logged.
|
||||
self.prefixs = [
|
||||
'/example'
|
||||
]
|
||||
|
||||
def __call__(self, request):
|
||||
_t = time.time() # Calculated execution time.
|
||||
response = self.get_response(request) # Get response from view function.
|
||||
_t = int((time.time() - _t) * 1000)
|
||||
|
||||
# If the url does not start with on of the prefixes above, then return response and dont save log.
|
||||
# (Remove these two lines below to log everything)
|
||||
# if not list(filter(request.get_full_path().startswith, self.prefixs)):
|
||||
# return response
|
||||
|
||||
# create data for log db
|
||||
db_data = {
|
||||
'endpoint': request.get_full_path(),
|
||||
'response_code': response.status_code,
|
||||
'method': request.method,
|
||||
'remote_address': self.get_client_ip(request),
|
||||
'exec_time': _t,
|
||||
'body_response': response.content.decode('utf-8'),
|
||||
'body_request': request.POST,
|
||||
'client_ip': self.get_client_ip(request),
|
||||
'browser_info': request.META['HTTP_USER_AGENT'],
|
||||
'log_created_at': str(datetime.now())
|
||||
}
|
||||
if request.user.is_authenticated:
|
||||
db_data.update({'user': serializers.serialize('json', [request.user, ])})
|
||||
db = TinyDB(f'logs/log.json')
|
||||
db.insert(db_data)
|
||||
return response
|
||||
|
||||
# get clients ip address
|
||||
def get_client_ip(self, request):
|
||||
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
|
||||
if x_forwarded_for:
|
||||
_ip = x_forwarded_for.split(',')[0]
|
||||
else:
|
||||
_ip = request.META.get('REMOTE_ADDR')
|
||||
return _ip
|
||||
21
apps/log/migrations/0001_initial.py
Normal file
21
apps/log/migrations/0001_initial.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# Generated by Django 5.0 on 2025-05-17 08:08
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Log',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('test', models.CharField(max_length=50, null=True)),
|
||||
],
|
||||
),
|
||||
]
|
||||
16
apps/log/migrations/0002_delete_log.py
Normal file
16
apps/log/migrations/0002_delete_log.py
Normal file
@@ -0,0 +1,16 @@
|
||||
# Generated by Django 4.2.21 on 2025-05-17 09:03
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('log', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.DeleteModel(
|
||||
name='Log',
|
||||
),
|
||||
]
|
||||
35
apps/log/migrations/0003_initial.py
Normal file
35
apps/log/migrations/0003_initial.py
Normal file
@@ -0,0 +1,35 @@
|
||||
# Generated by Django 4.2.21 on 2025-05-17 10:09
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('log', '0002_delete_log'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Req',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('create_date', models.DateTimeField(auto_now_add=True)),
|
||||
('modify_date', models.DateTimeField(auto_now=True)),
|
||||
('creator_info', models.CharField(max_length=100, null=True)),
|
||||
('modifier_info', models.CharField(max_length=100, null=True)),
|
||||
('trash', models.BooleanField(default=False)),
|
||||
('title', models.CharField(max_length=12)),
|
||||
('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createddby', to=settings.AUTH_USER_MODEL)),
|
||||
('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
]
|
||||
16
apps/log/migrations/0004_delete_req.py
Normal file
16
apps/log/migrations/0004_delete_req.py
Normal file
@@ -0,0 +1,16 @@
|
||||
# Generated by Django 4.2.21 on 2025-05-17 11:59
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('log', '0003_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.DeleteModel(
|
||||
name='Req',
|
||||
),
|
||||
]
|
||||
0
apps/log/migrations/__init__.py
Normal file
0
apps/log/migrations/__init__.py
Normal file
16
apps/log/models.py
Normal file
16
apps/log/models.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from django.db import models
|
||||
from apps.core.models import BaseModel
|
||||
from mongoengine import Document, fields
|
||||
# Create your models here.
|
||||
|
||||
|
||||
class Log(Document):
|
||||
endpoint = fields.StringField(max_length=100, null=True) # The url the user requested
|
||||
user = fields.StringField(max_length=200, null=True)
|
||||
response_code = fields.IntField(default=0) # Response status code
|
||||
method = fields.StringField(max_length=10, null=True) # Request method
|
||||
remote_address = fields.StringField(max_length=20, null=True) # IP address of user
|
||||
exec_time = fields.IntField(null=True) # Time taken to create the response
|
||||
date = fields.DateTimeField(auto_now=True) # Date and time of request
|
||||
body_response = fields.StringField(null=True) # Response data
|
||||
body_request = fields.StringField(max_length=1000, null=True) # Request data
|
||||
3
apps/log/tests.py
Normal file
3
apps/log/tests.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -1,3 +1,2 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
||||
from .models import Log
|
||||
0
apps/search/api/__init__.py
Normal file
0
apps/search/api/__init__.py
Normal file
0
apps/search/api/v1/__init__.py
Normal file
0
apps/search/api/v1/__init__.py
Normal file
61
apps/search/api/v1/api.py
Normal file
61
apps/search/api/v1/api.py
Normal file
@@ -0,0 +1,61 @@
|
||||
from .serializers import UserRelationDocumentSerializer
|
||||
from django_elasticsearch_dsl_drf.viewsets import DocumentViewSet
|
||||
from rest_framework.pagination import LimitOffsetPagination
|
||||
from apps.search.document.user_document import UserRelationDocument
|
||||
from django.http.response import HttpResponse
|
||||
from rest_framework.response import Response
|
||||
from apps.authentication.models import User
|
||||
from rest_framework.views import APIView
|
||||
from elasticsearch_dsl.query import Q
|
||||
import abc
|
||||
|
||||
|
||||
class PaginatedElasticSearchApiView(APIView, LimitOffsetPagination):
|
||||
"""Base ApiView Class for elasticsearch views with pagination,
|
||||
Other ApiView classes should inherit from this class"""
|
||||
serializer_class = None
|
||||
document_class = None
|
||||
|
||||
@abc.abstractmethod
|
||||
def generate_q_expression(self, query):
|
||||
"""This method should be overridden
|
||||
and return a Q() expression."""
|
||||
|
||||
def get(self, request, query):
|
||||
try:
|
||||
q = self.generate_q_expression(query)
|
||||
search = self.document_class.search().query(q)
|
||||
response = search.execute()
|
||||
|
||||
print(f"Found {response.hits.total.value} hit(s) for query: '{query}'")
|
||||
|
||||
results = self.paginate_queryset(response, request, view=self) # noqa
|
||||
serializer = self.serializer_class(results, many=True)
|
||||
return self.get_paginated_response(serializer.data)
|
||||
except Exception as e:
|
||||
return HttpResponse(e, status=500)
|
||||
|
||||
|
||||
class SearchUserDocumentApiView(PaginatedElasticSearchApiView):
|
||||
"""Base ApiView Class for elasticsearch views with pagination,
|
||||
Other ApiView classes should inherit from this class"""
|
||||
serializer_class = UserRelationDocumentSerializer
|
||||
document_class = UserRelationDocument
|
||||
|
||||
def generate_q_expression(self, query):
|
||||
return Q(
|
||||
'bool',
|
||||
should=[
|
||||
Q("match", user__username=query),
|
||||
Q("match", user__mobile=query),
|
||||
Q("match", user__national_code=query),
|
||||
Q("match", organization__type__key=query),
|
||||
Q("match", organization__name=query),
|
||||
Q("match", organization__city__name=query),
|
||||
Q("match", organization__province__name=query),
|
||||
Q("match", organization__national_unique_id=query),
|
||||
Q("match", organization__company_code=query),
|
||||
Q("match", role__role_name=query),
|
||||
],
|
||||
minimum_should_match=1,
|
||||
)
|
||||
15
apps/search/api/v1/serializers.py
Normal file
15
apps/search/api/v1/serializers.py
Normal file
@@ -0,0 +1,15 @@
|
||||
from django_elasticsearch_dsl_drf.serializers import DocumentSerializer
|
||||
from apps.search.documents import UserRelationDocument
|
||||
|
||||
|
||||
class UserRelationDocumentSerializer(DocumentSerializer):
|
||||
"""Serializer for user relation document."""
|
||||
|
||||
class Meta:
|
||||
document = UserRelationDocument
|
||||
fields = (
|
||||
'id',
|
||||
'user',
|
||||
'organization',
|
||||
'role'
|
||||
)
|
||||
10
apps/search/api/v1/urls.py
Normal file
10
apps/search/api/v1/urls.py
Normal file
@@ -0,0 +1,10 @@
|
||||
from django.urls import path, include
|
||||
from .api import SearchUserDocumentApiView
|
||||
from rest_framework import routers
|
||||
|
||||
router = routers.DefaultRouter()
|
||||
|
||||
urlpatterns = [
|
||||
path('', include(router.urls), name='search_user'),
|
||||
path('user_elastic/<str:query>/', SearchUserDocumentApiView.as_view()),
|
||||
]
|
||||
0
apps/search/api/v1/views.py
Normal file
0
apps/search/api/v1/views.py
Normal file
0
apps/search/api/v2/__init__.py
Normal file
0
apps/search/api/v2/__init__.py
Normal file
0
apps/search/api/v2/serializers.py
Normal file
0
apps/search/api/v2/serializers.py
Normal file
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user