From b2c8228d050cf1f3b1987b18fb1b43a8ce77e5b6 Mon Sep 17 00:00:00 2001 From: Bunga Amalia Kurniawati Date: Mon, 17 May 2021 16:12:51 +0700 Subject: [PATCH 1/7] [CHORES] memperbaharui gitignore --- .gitignore | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 2c929c8..9e6ac02 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,8 @@ __pycache__/ .env_var static env -.env \ No newline at end of file +.env +.scannerwork +.vscode +coverage.xml +media \ No newline at end of file -- GitLab From da37b5122d0a12695a4bb7c273e956a209f1ff29 Mon Sep 17 00:00:00 2001 From: Bunga Amalia Kurniawati Date: Mon, 17 May 2021 16:13:19 +0700 Subject: [PATCH 2/7] [CHORES] menambahkan properti SonarQube tambahan --- sonar-project.properties | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonar-project.properties b/sonar-project.properties index 43bcb24..9693910 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,3 +1,5 @@ +sonar.projectKey=ppl2021-a-pilar_be +sonar.branch.name=dev sonar.exclusions=**/schemas.py,**/seeds.py,**signals.py,**/tests.py,**/migrations/** sonar.python.coverage.reportPaths=coverage.xml sonar.scm.provider=git -- GitLab From 5f1ca217f31ec72865dcdd64949d8fc3548ae60a Mon Sep 17 00:00:00 2001 From: Bunga Amalia Kurniawati Date: Mon, 17 May 2021 16:13:46 +0700 Subject: [PATCH 3/7] [REFACTOR] menyelesaikan isu code smells --- api/reports_writer.py | 4 ++-- api/serializers.py | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/api/reports_writer.py b/api/reports_writer.py index 95a49ca..788e4ab 100644 --- a/api/reports_writer.py +++ b/api/reports_writer.py @@ -303,7 +303,7 @@ def create_transaction_report(filter_params): # pylint: disable=too-many-locals return buffer -def create_program_donation_report_CSH(filter_params): +def create_program_donation_report_csh(filter_params): buffer = io.BytesIO() workbook = xlsxwriter.Workbook( buffer, @@ -373,7 +373,7 @@ def create_program_donation_report_CSH(filter_params): workbook.close() return buffer -def create_program_donation_report_GDS(filter_params): +def create_program_donation_report_gds(filter_params): buffer = io.BytesIO() workbook = xlsxwriter.Workbook( buffer, diff --git a/api/serializers.py b/api/serializers.py index 4e325d0..e2e7d59 100644 --- a/api/serializers.py +++ b/api/serializers.py @@ -487,7 +487,6 @@ class ProgramProgressSerializer(serializers.ModelSerializer): def validate(self, attrs): instance = self.instance - date = attrs.get('date', getattr(instance, 'date', None)) errors = {} if errors: raise serializers.ValidationError(errors) -- GitLab From 0e02018fc55ac9ce75e656153df822e4702821f6 Mon Sep 17 00:00:00 2001 From: Bunga Amalia Kurniawati Date: Tue, 25 May 2021 10:54:24 +0700 Subject: [PATCH 4/7] [REFACTOR] memperbaiki penamaan fungsi pada views --- api/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/views.py b/api/views.py index 7f0b05b..b985404 100644 --- a/api/views.py +++ b/api/views.py @@ -452,7 +452,7 @@ class ReportTransaction(ReportAPIView): class ReportProgramDonationCSH(ReportAPIView): - report_function = reports_writer.create_program_donation_report_CSH + report_function = reports_writer.create_program_donation_report_csh schema = schemas.ReportProgramDonationSchema() serializer_class = api_serializers.ReportProgramDonationSerializer @@ -466,7 +466,7 @@ class ReportProgramDonationCSH(ReportAPIView): return filename class ReportProgramDonationGDS(ReportAPIView): - report_function = reports_writer.create_program_donation_report_GDS + report_function = reports_writer.create_program_donation_report_gds schema = schemas.ReportProgramDonationSchema() serializer_class = api_serializers.ReportProgramDonationSerializer -- GitLab From de51fb4ed6e773b2dab2b99ab2daeb395372fc29 Mon Sep 17 00:00:00 2001 From: Bunga Amalia Kurniawati Date: Tue, 25 May 2021 11:33:16 +0700 Subject: [PATCH 5/7] [REFACTOR] memisahkan file views untuk setiap fitur --- api/views.py | 1043 -------------------------------------- api/views/__init__.py | 12 + api/views/auth.py | 95 ++++ api/views/bank.py | 42 ++ api/views/batch.py | 97 ++++ api/views/cart.py | 249 +++++++++ api/views/choices.py | 43 ++ api/views/config.py | 50 ++ api/views/donation.py | 128 +++++ api/views/product.py | 194 +++++++ api/views/program.py | 159 ++++++ api/views/report.py | 90 ++++ api/views/transaction.py | 64 +++ api/views/user.py | 51 ++ 14 files changed, 1274 insertions(+), 1043 deletions(-) delete mode 100644 api/views.py create mode 100644 api/views/__init__.py create mode 100644 api/views/auth.py create mode 100644 api/views/bank.py create mode 100644 api/views/batch.py create mode 100644 api/views/cart.py create mode 100644 api/views/choices.py create mode 100644 api/views/config.py create mode 100644 api/views/donation.py create mode 100644 api/views/product.py create mode 100644 api/views/program.py create mode 100644 api/views/report.py create mode 100644 api/views/transaction.py create mode 100644 api/views/user.py diff --git a/api/views.py b/api/views.py deleted file mode 100644 index b985404..0000000 --- a/api/views.py +++ /dev/null @@ -1,1043 +0,0 @@ -from django import http, shortcuts -from django.contrib import auth -from django.db import transaction as db_transaction, utils as db_utils -from django.db.models import deletion -from django.utils import timezone -from django.utils.translation import gettext_lazy as _ -from django_filters import rest_framework -from knox import views as knox_views -from rest_framework import ( - exceptions as rest_framework_exceptions, filters as rest_framework_filters, generics, - permissions as rest_framework_permissions, response, status, views as rest_framework_views -) -from rest_framework.authtoken import serializers as authtoken_serializers -from rest_framework.decorators import api_view -from django.views.decorators.csrf import csrf_exempt -from api import ( - constants, exceptions as api_exceptions, filters as api_filters, models, paginations, - permissions as api_permissions, reports_writer, schemas, serializers as api_serializers, - utils as api_utils -) -from home_industry import utils as home_industry_utils - - -class AuthRegister(generics.CreateAPIView): - permission_classes = [api_permissions.IsAnonymousUser] - serializer_class = api_serializers.UserSerializer - - -class AuthCredLogin(knox_views.LoginView): - permission_classes = [rest_framework_permissions.AllowAny] - serializer_class = authtoken_serializers.AuthTokenSerializer - - def get_serializer(self, *args, **kwargs): - return self.serializer_class(*args, **kwargs) - - def post(self, request, format=None): # pylint: disable=redefined-builtin - serializer = self.get_serializer(data=request.data) - serializer.is_valid(raise_exception=True) - user = serializer.validated_data['user'] - auth.login(request, user) - return super().post(request, format) - - -class AuthPhoneNumberLogin(rest_framework_views.APIView): - permission_classes = [rest_framework_permissions.AllowAny] - serializer_class = api_serializers.PhoneNumberSerializer - - def get_serializer(self, *args, **kwargs): - return self.serializer_class(*args, **kwargs) - - def post(self, request, _format=None): - serializer = self.get_serializer(data=request.data) - serializer.is_valid(raise_exception=True) - user = shortcuts.get_object_or_404( - models.User, - phone_number=serializer.validated_data['phone_number'] - ) - user.otp = api_utils.generate_otp() - user.save() - api_utils.send_otp(str(user.phone_number), user.otp) - token = api_utils.generate_bearer_token(user) - return response.Response({'token': token}, status=status.HTTP_200_OK) - - -class AuthOTPLogin(knox_views.LoginView): - permission_classes = [rest_framework_permissions.AllowAny] - serializer_class = api_serializers.OTPSerializer - - def get_serializer(self, *args, **kwargs): - return self.serializer_class(*args, **kwargs) - - def post(self, request, format=None): # pylint: disable=redefined-builtin - http_authorization = self.request.META.get('HTTP_AUTHORIZATION') - username = api_utils.get_username_from_bearer_token(http_authorization) - serializer = self.get_serializer(data=request.data) - serializer.is_valid(raise_exception=True) - user = shortcuts.get_object_or_404(models.User, username=username) - if user.otp != serializer.validated_data['otp']: - return response.Response(status=status.HTTP_400_BAD_REQUEST) - auth.login(request, user) - user.otp = '' - user.save() - return super().post(request, format) - - -class AuthResendOTP(rest_framework_views.APIView): - permission_classes = [rest_framework_permissions.AllowAny] - - def post(self, request, _format=None): - http_authorization = self.request.META.get('HTTP_AUTHORIZATION') - username = api_utils.get_username_from_bearer_token(http_authorization) - user = shortcuts.get_object_or_404(models.User, username=username) - user.otp = api_utils.generate_otp() - user.save() - api_utils.send_otp(str(user.phone_number), user.otp) - return response.Response(status=status.HTTP_204_NO_CONTENT) - - -class CartUpdate(rest_framework_views.APIView): - permission_classes = [rest_framework_permissions.IsAuthenticated] - serializer_class = api_serializers.CartUpdateSerializer - - def get_serializer(self, *args, **kwargs): - return self.serializer_class(*args, **kwargs) - - def post(self, request, _format=None): - serializer = self.get_serializer(data=request.data) - serializer.is_valid(raise_exception=True) - user = request.user - product = shortcuts.get_object_or_404( - models.Product, - id=serializer.validated_data['product'] - ) - shopping_cart = models.ShoppingCart.objects.get(user=user) - cart_item, _created = models.CartItem.objects.get_or_create( - product=product, - shopping_cart=shopping_cart - ) - if serializer.validated_data['quantity'] == 0: - cart_item.delete() - else: - cart_item.quantity = serializer.validated_data['quantity'] - cart_item.save() - return response.Response(status=status.HTTP_204_NO_CONTENT) - - -class CartOverview(rest_framework_views.APIView): - permission_classes = [rest_framework_permissions.IsAuthenticated] - - def get(self, request, _format=None): - user = request.user - shopping_cart = models.ShoppingCart.objects.get(user=user) - item_subtotal = sum( - cart_item.product.price * cart_item.quantity - for cart_item in shopping_cart.cart_items.all() - ) - shipping_costs = api_utils.get_shipping_costs(user) - if shipping_costs is None: - return response.Response( - {'item_subtotal': str(item_subtotal)}, - status=status.HTTP_200_OK - ) - return response.Response( - {'item_subtotal': str(item_subtotal), 'shipping_costs': str(shipping_costs)}, - status=status.HTTP_200_OK - ) - - -class CartCheckout(rest_framework_views.APIView): - permission_classes = [rest_framework_permissions.IsAuthenticated] - serializer_class = api_serializers.CartCheckoutSerializer - - def get_serializer(self, *args, **kwargs): - return self.serializer_class(*args, **kwargs) - - def post(self, request, _format=None): - serializer = self.get_serializer(data=request.data) - serializer.is_valid(raise_exception=True) - user = request.user - shipment_config = home_industry_utils.get_shipment_config() - if user.sub_district.lower() != shipment_config.sub_district.lower(): - raise rest_framework_exceptions.ParseError(_( # pylint: disable=no-member - 'Cannot process shipment to other sub-districts other than {sub_district}.' - ).format(sub_district=shipment_config.sub_district)) - shopping_cart = models.ShoppingCart.objects.get(user=user) - cart_items = shopping_cart.cart_items.all() - if not cart_items.exists(): - raise rest_framework_exceptions.ParseError(_( - 'Unable to checkout because there are no items purchased.' - )) - api_utils.validate_product_stock(cart_items) - transaction_status = ( - '001' if serializer.validated_data['payment_method'] == 'TRF' else '002' - ) - - transaction = models.Transaction.objects.create( - user=user, - payment_method=serializer.validated_data['payment_method'], - donation=serializer.validated_data['donation'], - transaction_status=transaction_status, - batch = ( - None if serializer.validated_data['payment_method'] == 'TRF' - else models.Batch.objects.filter( - start_date__lte=timezone.now().date(), - end_date__gte=timezone.now().date()).first() - ) - ) - - is_success = True - for cart_item in cart_items: - product = cart_item.product - if product.stock is not None: - try: - with db_transaction.atomic(): - product.stock -= cart_item.quantity - product.total_profit += cart_item.quantity*product.profit - product.save() - except db_utils.IntegrityError: - is_success = False - models.TransactionItem.objects.create( - transaction=transaction, - product=product, - quantity=cart_item.quantity - ) - cart_item.delete() - if not is_success: - transaction.transaction_status = '007' - transaction.save() - raise rest_framework_exceptions.APIException(_('Checkout failed.')) - return response.Response({'transaction': transaction.id}, status=status.HTTP_200_OK) - - -class CartUploadPOP(rest_framework_views.APIView): - permission_classes = [rest_framework_permissions.IsAuthenticated] - serializer_class = api_serializers.CartUploadPOPSerializer - - def get_serializer(self, *args, **kwargs): - return self.serializer_class(*args, **kwargs) - - def post(self, request, _format=None): - serializer = self.get_serializer(data=request.data) - serializer.is_valid(raise_exception=True) - user = request.user - bank_account_transfer_destination = shortcuts.get_object_or_404( - models.BankAccountTransferDestination, - id=serializer.validated_data['bank_account_transfer_destination'] - ) - transaction = shortcuts.get_object_or_404( - models.Transaction, - id=serializer.validated_data['transaction'], - user=user - ) - if transaction.payment_method != 'TRF': - raise rest_framework_exceptions.PermissionDenied(_( - 'The payment method for this transaction is not a transfer.' - )) - if transaction.transaction_status not in ('001', '002'): - raise rest_framework_exceptions.PermissionDenied(_( - 'Cannot upload proof of payment at this stage.' - )) - transaction.proof_of_payment = serializer.validated_data['proof_of_payment'] - transaction.user_bank_name = serializer.validated_data['user_bank_name'] - transaction.user_bank_account_name = serializer.validated_data['user_bank_account_name'] - transaction.bank_account_transfer_destination = bank_account_transfer_destination - transaction.update_bank_account_transfer_destination = True - transaction.transaction_status = '002' - transaction.batch = models.Batch.objects.filter( - start_date__lte=timezone.now().date(), - end_date__gte=timezone.now().date()).first() - transaction.save() - return response.Response(status=status.HTTP_204_NO_CONTENT) - - -class CartCompleteTransaction(rest_framework_views.APIView): - permission_classes = [rest_framework_permissions.IsAuthenticated] - serializer_class = api_serializers.CartCompleteOrCancelTransactionSerializer - - def get_serializer(self, *args, **kwargs): - return self.serializer_class(*args, **kwargs) - - def post(self, request, _format=None): - serializer = self.get_serializer(data=request.data) - serializer.is_valid(raise_exception=True) - transaction = shortcuts.get_object_or_404( - models.Transaction, - id=serializer.validated_data['transaction'], - user=request.user - ) - if transaction.transaction_status != '004': - raise rest_framework_exceptions.PermissionDenied(_( - 'Transaction cannot be completed unless the status is "Being shipped".' - )) - transaction.transaction_status = '005' - transaction.save() - return response.Response(status=status.HTTP_204_NO_CONTENT) - - -class CartCancelTransaction(rest_framework_views.APIView): - permission_classes = [rest_framework_permissions.IsAuthenticated] - serializer_class = api_serializers.CartCompleteOrCancelTransactionSerializer - - def get_serializer(self, *args, **kwargs): - return self.serializer_class(*args, **kwargs) - - def post(self, request, _format=None): - serializer = self.get_serializer(data=request.data) - serializer.is_valid(raise_exception=True) - user = request.user - transaction = shortcuts.get_object_or_404( - models.Transaction, - id=serializer.validated_data['transaction'], - user=user - ) - if transaction.transaction_status not in ('001', '002'): - raise rest_framework_exceptions.PermissionDenied(_( - 'Transaction cannot be canceled at this stage.' - )) - transaction_items = transaction.transaction_items.all() - api_utils.return_transaction_items_to_product_stock(transaction_items) - transaction.transaction_status = '006' - transaction.save() - return response.Response(status=status.HTTP_204_NO_CONTENT) - - -class DonationCreate(rest_framework_views.APIView): - permission_classes = [rest_framework_permissions.IsAuthenticated] - serializer_class = api_serializers.DonationCreateSerializer - - def get_serializer(self, *args, **kwargs): - return self.serializer_class(*args, **kwargs) - - def post(self, request, _format=None): - serializer = self.get_serializer(data=request.data) - serializer.is_valid(raise_exception=True) - user = request.user - program = shortcuts.get_object_or_404( - models.Program, - id=serializer.validated_data['program'] - ) - if not program.open_donation: - raise rest_framework_exceptions.PermissionDenied(_( - 'This program is currently not accepting donations.' - )) - program_donation = None - if serializer.validated_data['donation_type'] == 'CSH': - bank_account_transfer_destination = shortcuts.get_object_or_404( - models.BankAccountTransferDestination, - id=serializer.validated_data['bank_account_transfer_destination'] - ) - program_donation = models.ProgramDonation.objects.create( - user=user, - program=program, - donation_type='CSH', - amount=serializer.validated_data['amount'], - proof_of_bank_transfer=serializer.validated_data['proof_of_bank_transfer'], - user_bank_name=serializer.validated_data['user_bank_name'], - user_bank_account_name=serializer.validated_data['user_bank_account_name'], - bank_account_transfer_destination=bank_account_transfer_destination - ) - - else: - if serializer.validated_data['delivery_method'] == 'DLV': - program_donation = models.ProgramDonation.objects.create( - user=user, - program=program, - donation_type='GDS', - goods_quantity=serializer.validated_data['goods_quantity'], - goods_description=serializer.validated_data['goods_description'], - delivery_method=serializer.validated_data['delivery_method'], - delivery_address=None - ) - else: - program_donation = models.ProgramDonation.objects.create( - user=user, - program=program, - donation_type='GDS', - goods_quantity=serializer.validated_data['goods_quantity'], - goods_description=serializer.validated_data['goods_description'], - delivery_method=serializer.validated_data['delivery_method'], - delivery_address=serializer.validated_data['delivery_address'] - ) - - return response.Response( - {'program_donation': program_donation.id}, - status=status.HTTP_200_OK - ) - - - -class DonationReuploadProofOfBankTransfer(rest_framework_views.APIView): - permission_classes = [rest_framework_permissions.IsAuthenticated] - serializer_class = api_serializers.DonationReuploadProofOfBankTransferSerializer - - def get_serializer(self, *args, **kwargs): - return self.serializer_class(*args, **kwargs) - - def post(self, request, _format=None): - serializer = self.get_serializer(data=request.data) - serializer.is_valid(raise_exception=True) - user = request.user - bank_account_transfer_destination = shortcuts.get_object_or_404( - models.BankAccountTransferDestination, - id=serializer.validated_data['bank_account_transfer_destination'] - ) - program_donation = shortcuts.get_object_or_404( - models.ProgramDonation, - id=serializer.validated_data['program_donation'], - user=user - ) - if program_donation.donation_status not in ('001', '004'): - raise rest_framework_exceptions.PermissionDenied(_( - 'Cannot reupload proof of bank transfer at this stage.' - )) - if program_donation.donation_type != 'CSH': - raise rest_framework_exceptions.PermissionDenied(_( - 'Cannot proof of bank transfer foor good donation.' - )) - program_donation.amount = serializer.validated_data['amount'] - program_donation.proof_of_bank_transfer = ( - serializer.validated_data['proof_of_bank_transfer'] - ) - program_donation.user_bank_name = serializer.validated_data['user_bank_name'] - program_donation.user_bank_account_name = ( - serializer.validated_data['user_bank_account_name'] - ) - program_donation.bank_account_transfer_destination = bank_account_transfer_destination - program_donation.update_bank_account_transfer_destination = True - program_donation.donation_status = '001' - program_donation.save() - return response.Response(status=status.HTTP_204_NO_CONTENT) - - -class ReportAPIView(rest_framework_views.APIView): - permission_classes = [rest_framework_permissions.IsAdminUser] - report_function = None - serializer_class = None - - def get_filename(self, query_params): - raise NotImplementedError - - def get_serializer(self, *args, **kwargs): - return self.serializer_class(*args, **kwargs) # pylint: disable=not-callable - - def get(self, request, _format=None): - assert self.report_function is not None, ( - '{} should include a `report_function` attribute.'.format(self.__class__.__name__) - ) - assert self.report_function is not None, ( - '{} should include a `serializer_class` attribute.'.format(self.__class__.__name__) - ) - serializer = self.get_serializer(data=request.query_params) - serializer.is_valid(raise_exception=True) - buffer = self.report_function.__func__(serializer.validated_data) - buffer.seek(0) - return http.FileResponse(buffer, filename=self.get_filename(serializer.validated_data)) - - -class ReportTransaction(ReportAPIView): - report_function = reports_writer.create_transaction_report - schema = schemas.ReportTransactionSchema() - serializer_class = api_serializers.ReportTransactionSerializer - - def get_filename(self, query_params): - filename = '{}.xlsx'.format(_( # pylint: disable=no-member - 'Transaction Report from {date_from} to {date_to} for {batch_name}' - ).format( - date_from=query_params.get('created_at_date_range_after', '_'), - date_to=query_params.get('created_at_date_range_before', str(timezone.now())[:10]), - batch_name=query_params.get('batch_name', '_') - )) - return filename - - -class ReportProgramDonationCSH(ReportAPIView): - report_function = reports_writer.create_program_donation_report_csh - schema = schemas.ReportProgramDonationSchema() - serializer_class = api_serializers.ReportProgramDonationSerializer - - def get_filename(self, query_params): - filename = '{}.xlsx'.format(_( # pylint: disable=no-member - 'Program Donation Report from {date_from} to {date_to}' - ).format( - date_from=query_params.get('created_at_date_range_after', '_'), - date_to=query_params.get('created_at_date_range_before', str(timezone.now())[:10]) - )) - return filename - -class ReportProgramDonationGDS(ReportAPIView): - report_function = reports_writer.create_program_donation_report_gds - schema = schemas.ReportProgramDonationSchema() - serializer_class = api_serializers.ReportProgramDonationSerializer - - def get_filename(self, query_params): - filename = '{}.xlsx'.format(_( # pylint: disable=no-member - 'Program Donation Report from {date_from} to {date_to}' - ).format( - date_from=query_params.get('created_at_date_range_after', '_'), - date_to=query_params.get('created_at_date_range_before', str(timezone.now())[:10]) - )) - return filename - - -class UserList(generics.ListCreateAPIView): - filter_backends = [ - rest_framework.DjangoFilterBackend, - rest_framework_filters.OrderingFilter, - rest_framework_filters.SearchFilter, - ] - filterset_fields = ['username', 'phone_number'] - ordering_fields = [ - 'username', 'full_name', 'phone_number', - 'total_transactions', 'total_program_donations_goods', 'total_program_donations_cash' - ] - pagination_class = paginations.SmallResultsSetPagination - permission_classes = [rest_framework_permissions.IsAdminUser] - queryset = models.User.objects.all() - search_fields = ['username', 'full_name', 'phone_number'] - serializer_class = api_serializers.UserSerializer - -class UserDetail(generics.RetrieveUpdateDestroyAPIView): - permission_classes = [ - api_permissions.IsAdminUserOrSelf, - rest_framework_permissions.IsAuthenticated, - ] - queryset = models.User.objects.all() - serializer_class = api_serializers.UserSerializer - - def get_object(self): - if self.kwargs.get('pk') == 'self': - self.kwargs['pk'] = self.request.user.id - return super().get_object() - - -class BankAccountTransferDestinationList(generics.ListCreateAPIView): - filter_backends = [rest_framework_filters.SearchFilter] - pagination_class = paginations.SmallResultsSetPagination - permission_classes = [ - api_permissions.IsAdminUserOrReadOnly, - rest_framework_permissions.IsAuthenticated, - ] - queryset = models.BankAccountTransferDestination.objects.all() - search_fields = ['bank_name', 'bank_account_number', 'bank_account_name'] - serializer_class = api_serializers.BankAccountTransferDestinationSerializer - - -class BankAccountTransferDestinationDetail(generics.RetrieveUpdateDestroyAPIView): - permission_classes = [ - api_permissions.IsAdminUserOrReadOnly, - rest_framework_permissions.IsAuthenticated, - ] - queryset = models.BankAccountTransferDestination.objects.all() - serializer_class = api_serializers.BankAccountTransferDestinationSerializer - - -class CategoryList(generics.ListCreateAPIView): - filter_backends = [ - rest_framework.DjangoFilterBackend, - rest_framework_filters.OrderingFilter, - rest_framework_filters.SearchFilter, - ] - filterset_fields = ['name'] - ordering_fields = ['name'] - pagination_class = paginations.SmallResultsSetPagination - permission_classes = [ - api_permissions.IsAdminUserOrReadOnly, - rest_framework_permissions.IsAuthenticated, - ] - queryset = models.Category.objects.all() - search_fields = ['name'] - serializer_class = api_serializers.CategorySerializer - - -class CategoryDetail(generics.RetrieveUpdateDestroyAPIView): - permission_classes = [ - api_permissions.IsAdminUserOrReadOnly, - rest_framework_permissions.IsAuthenticated, - ] - queryset = models.Category.objects.all() - serializer_class = api_serializers.CategorySerializer - - def destroy(self, request, *_args, **_kwargs): - instance = self.get_object() - try: - instance.delete() - except deletion.ProtectedError: - raise api_exceptions.IntegrityError(_( - 'Cannot delete category due to integrity error.' - )) - return response.Response(status=status.HTTP_204_NO_CONTENT) - - -class SubcategoryList(generics.ListCreateAPIView): - filter_backends = [ - rest_framework.DjangoFilterBackend, - rest_framework_filters.OrderingFilter, - rest_framework_filters.SearchFilter, - ] - filterset_fields = ['name', 'category'] - ordering_fields = ['name'] - pagination_class = paginations.SmallResultsSetPagination - permission_classes = [ - api_permissions.IsAdminUserOrReadOnly, - rest_framework_permissions.IsAuthenticated, - ] - queryset = models.Subcategory.objects.all() - search_fields = ['name'] - serializer_class = api_serializers.SubcategorySerializer - - -class SubcategoryDetail(generics.RetrieveUpdateDestroyAPIView): - permission_classes = [ - api_permissions.IsAdminUserOrReadOnly, - rest_framework_permissions.IsAuthenticated, - ] - queryset = models.Subcategory.objects.all() - serializer_class = api_serializers.SubcategorySerializer - - def destroy(self, request, *_args, **_kwargs): - instance = self.get_object() - try: - instance.delete() - except deletion.ProtectedError: - raise api_exceptions.IntegrityError(_( - 'Cannot delete subcategory due to integrity error.' - )) - return response.Response(status=status.HTTP_204_NO_CONTENT) - - -class ProductList(generics.ListCreateAPIView): - filter_backends = [ - rest_framework.DjangoFilterBackend, - rest_framework_filters.OrderingFilter, - rest_framework_filters.SearchFilter, - ] - filterset_fields = ['code', 'subcategory', 'subcategory__category'] - ordering_fields = ['name', 'price', 'stock'] - pagination_class = paginations.SmallResultsSetPagination - permission_classes = [ - api_permissions.IsAdminUserOrReadOnly, - rest_framework_permissions.IsAuthenticated, - ] - queryset = models.Product.objects.all() - search_fields = ['code', 'name'] - serializer_class = api_serializers.ProductSerializer - - def post(self, request, _format=None): - serializer = self.get_serializer(data=request.data) - serializer.is_valid(raise_exception=True) - validated_image = None - try: - validated_image = serializer.validated_data['image'] - except KeyError: - pass - product = models.Product.objects.create( - name=serializer.validated_data['name'], - description=serializer.validated_data['description'], - price=serializer.validated_data['price'], - stock=serializer.validated_data['stock'], - modal=serializer.validated_data['modal'], - subcategory=models.Subcategory.objects.get(name=serializer.validated_data['subcategory']), - total_profit=0, - unit=serializer.validated_data['unit'], - image=validated_image - ) - product.profit= (product.price - product.modal) - product.save() - return response.Response( - {'id': product.id}, - status=status.HTTP_201_CREATED - ) - - - -class ProductDetail(generics.RetrieveUpdateDestroyAPIView): - permission_classes = [ - api_permissions.IsAdminUserOrReadOnly, - rest_framework_permissions.IsAuthenticated, - ] - queryset = models.Product.objects.all() - serializer_class = api_serializers.ProductSerializer - - def get_serializer(self, *args, **kwargs): - # leave this intact - serializer_class = self.get_serializer_class() - kwargs["context"] = self.get_serializer_context() - - - - if (self.request != None): - if (self.request.data.get("price") != None) and (self.request.data.get("modal") != None): - draft_request_data = self.request.data.copy() - profit= int(self.request.data['price'])-int(self.request.data['modal']) - new_profit={'profit': profit} - draft_request_data.update(new_profit) - kwargs["data"] = draft_request_data - return serializer_class(*args, **kwargs) - else: - if (self.request.data.get("price") != None): - - instance=self.get_object() - draft_request_data = self.request.data.copy() - profit= int(self.request.data['price'])-int(instance.modal) - new_profit={'profit': profit} - draft_request_data.update(new_profit) - - kwargs["data"] = draft_request_data - return serializer_class(*args, **kwargs) - elif (self.request.data.get("modal") != None): - instance=self.get_object() - draft_request_data = self.request.data.copy() - profit= int(instance.price)-int(self.request.data['modal']) - new_profit={'profit': profit} - draft_request_data.update(new_profit) - - kwargs["data"] = draft_request_data - return serializer_class(*args, **kwargs) - - return serializer_class(*args, **kwargs) - - def partial_update(self, request, *args, **kwargs): - instance = self.get_object() - - serializer = self.get_serializer(instance,data=request.data, partial=True) - serializer.is_valid(raise_exception=True) - - return super().partial_update(request, *args, **kwargs) # pylint: disable=no-member - - - -class ProgramProgressList(generics.ListCreateAPIView): - permission_classes = [ - api_permissions.IsAdminUserOrReadOnly, - rest_framework_permissions.IsAuthenticated, - ] - lookup_field = 'program' - serializer_class = api_serializers.ProgramProgressSerializer - - def get_queryset(self): - return models.ProgramProgress.objects.filter(program=self.get_program()) - - def perform_create(self, serializer): - serializer.save(program=self.get_program()) - - def get_program(self): - program = models.Program.objects.filter(id=self.kwargs.get(self.lookup_field)).first() - if program is None: - raise rest_framework_exceptions.NotFound(_( - 'Program not found.' - )) - return program - - -class ShoppingCartList(generics.ListAPIView): - filter_backends = [rest_framework.DjangoFilterBackend] - filterset_fields = ['user'] - pagination_class = paginations.SmallResultsSetPagination - permission_classes = [rest_framework_permissions.IsAdminUser] - queryset = models.ShoppingCart.objects.all() - serializer_class = api_serializers.ShoppingCartSerializer - - -class ShoppingCartDetail(generics.RetrieveAPIView): - permission_classes = [ - api_permissions.IsAdminUserOrOwner, - rest_framework_permissions.IsAuthenticated, - ] - queryset = models.ShoppingCart.objects.all() - serializer_class = api_serializers.ShoppingCartSerializer - - def get_object(self): - if self.kwargs.get('pk') == 'self': - self.kwargs['pk'] = models.ShoppingCart.objects.get(user=self.request.user).id - return super().get_object() - - -class TransactionList(generics.ListAPIView): - filter_backends = [ - rest_framework.DjangoFilterBackend, - rest_framework_filters.OrderingFilter, - rest_framework_filters.SearchFilter, - ] - filterset_class = api_filters.TransactionFilter - ordering_fields = ['created_at', 'updated_at'] - pagination_class = paginations.SmallResultsSetPagination - permission_classes = [rest_framework_permissions.IsAuthenticated] - queryset = models.Transaction.objects.all() - schema = schemas.TransactionListSchema() - search_fields = ['transaction_number', 'user_full_name'] - serializer_class = api_serializers.TransactionSerializer - - def filter_queryset(self, queryset): - queryset = super().filter_queryset(queryset) - if not self.request.user.is_staff: - return queryset.filter(user=self.request.user) - return queryset - - -class TransactionDetail(generics.RetrieveUpdateAPIView): - permission_classes = [ - api_permissions.IsAdminUserOrOwnerReadOnly, - rest_framework_permissions.IsAuthenticated, - ] - queryset = models.Transaction.objects.all() - serializer_class = api_serializers.TransactionSerializer - - def update(self, request, *args, **kwargs): - instance = self.get_object() - serializer = self.get_serializer(data=request.data) - serializer.is_valid(raise_exception=True) - if instance.transaction_status in ('005', '006', '007'): - raise rest_framework_exceptions.PermissionDenied(_( - 'Cannot update transaction because it has a completed, canceled, or failed status.' - )) - if serializer.validated_data['transaction_status'] == '006': - transaction_items = instance.transaction_items.all() - api_utils.return_transaction_items_to_product_stock(transaction_items) - return super().update(request, *args, **kwargs) # pylint: disable=no-member - - -class ProgramList(generics.ListCreateAPIView): - filter_backends = [ - rest_framework.DjangoFilterBackend, - rest_framework_filters.OrderingFilter, - rest_framework_filters.SearchFilter, - ] - filterset_fields = ['code'] - ordering_fields = ['name', 'start_date_time', 'end_date_time'] - pagination_class = paginations.SmallResultsSetPagination - permission_classes = [ - api_permissions.IsAdminUserOrReadOnly, - rest_framework_permissions.IsAuthenticated, - ] - queryset = models.Program.objects.all() - search_fields = ['code', 'name'] - serializer_class = api_serializers.ProgramSerializer - - -class ProgramDetail(generics.RetrieveUpdateDestroyAPIView): - permission_classes = [ - api_permissions.IsAdminUserOrReadOnly, - rest_framework_permissions.IsAuthenticated, - ] - queryset = models.Program.objects.all() - serializer_class = api_serializers.ProgramSerializer - -class ProgramDonationList(generics.ListAPIView): - filter_backends = [ - rest_framework.DjangoFilterBackend, - rest_framework_filters.OrderingFilter, - rest_framework_filters.SearchFilter, - ] - filterset_class = api_filters.ProgramDonationFilter - ordering_fields = ['created_at', 'updated_at'] - pagination_class = paginations.SmallResultsSetPagination - permission_classes = [rest_framework_permissions.IsAuthenticated] - queryset = models.ProgramDonation.objects.all() - schema = schemas.ProgramDonationListSchema() - search_fields = ['donation_number', 'user_full_name', 'program_name', 'donation_type'] - serializer_class = api_serializers.ProgramDonationSerializer - - def filter_queryset(self, queryset): - queryset = super().filter_queryset(queryset) - if not self.request.user.is_staff: - return queryset.filter(user=self.request.user) - return queryset - -@api_view(['DELETE']) -@csrf_exempt -def delete_donation_by_program(request, pid): - if ((request.user) and (request.user.is_staff)): - program = models.Program.objects.get(id=pid) - donation = models.ProgramDonation.objects.filter(program=program) - donation.delete() - return response.Response(status=status.HTTP_204_NO_CONTENT) - -class ProgramDonationListCSH(generics.ListAPIView): - filter_backends = [ - rest_framework.DjangoFilterBackend, - rest_framework_filters.OrderingFilter, - rest_framework_filters.SearchFilter, - ] - filterset_class = api_filters.ProgramDonationFilter - ordering_fields = ['created_at', 'updated_at'] - pagination_class = paginations.SmallResultsSetPagination - permission_classes = [rest_framework_permissions.IsAuthenticated] - queryset = models.ProgramDonation.objects.filter(donation_type='CSH') - schema = schemas.ProgramDonationListSchema() - search_fields = ['donation_number', 'user_full_name', 'program_name', 'donation_type'] - serializer_class = api_serializers.ProgramDonationSerializer - - def filter_queryset(self, queryset): - queryset = super().filter_queryset(queryset) - if not self.request.user.is_staff: - return queryset.filter(user=self.request.user) - return queryset - -class ProgramDonationListGDS(generics.ListAPIView): - filter_backends = [ - rest_framework.DjangoFilterBackend, - rest_framework_filters.OrderingFilter, - rest_framework_filters.SearchFilter, - ] - filterset_class = api_filters.ProgramDonationFilter - ordering_fields = ['created_at', 'updated_at'] - pagination_class = paginations.SmallResultsSetPagination - permission_classes = [rest_framework_permissions.IsAuthenticated] - queryset = models.ProgramDonation.objects.filter(donation_type='GDS') - schema = schemas.ProgramDonationListSchema() - search_fields = ['donation_number', 'user_full_name', 'program_name', 'donation_type'] - serializer_class = api_serializers.ProgramDonationSerializer - - def filter_queryset(self, queryset): - queryset = super().filter_queryset(queryset) - if not self.request.user.is_staff: - return queryset.filter(user=self.request.user) - return queryset - -class ProgramDonationDetail(generics.RetrieveUpdateAPIView): - permission_classes = [ - api_permissions.IsAdminUserOrOwnerReadOnly, - rest_framework_permissions.IsAuthenticated, - ] - queryset = models.ProgramDonation.objects.all() - serializer_class = api_serializers.ProgramDonationSerializer - - def update(self, request, *args, **kwargs): - instance = self.get_object() - serializer = self.get_serializer(data=request.data) - serializer.is_valid(raise_exception=True) - if instance.donation_status in ('002', '003'): - raise rest_framework_exceptions.PermissionDenied(_( - 'Cannot update program donation because it has a completed or canceled status.' - )) - return super().update(request, *args, **kwargs) # pylint: disable=no-member - - -class ChoicesAPIView(rest_framework_views.APIView): - choices = None - permission_classes = [rest_framework_permissions.IsAuthenticated] - - def get(self, request, _format=None): - assert self.choices is not None, ( - '{} should include a `choices` attribute.'.format(self.__class__.__name__) - ) - return response.Response(api_utils.map_choices(self.choices), status=status.HTTP_200_OK) - - -class PaymentMethodChoices(ChoicesAPIView): - choices = constants.PAYMENT_METHOD_CHOICES - - -class TransactionStatusChoices(ChoicesAPIView): - choices = constants.TRANSACTION_STATUS_CHOICES - - -class DonationStatusChoices(ChoicesAPIView): - choices = constants.DONATION_STATUS_CHOICES - - -class AppConfigDetail(generics.RetrieveUpdateAPIView): - permission_classes = [rest_framework_permissions.IsAdminUser] - queryset = models.AppConfig.objects.all() - serializer_class = api_serializers.AppConfigSerializer - - def get_object(self): - obj = shortcuts.get_object_or_404(models.AppConfig) - return obj - - -class HelpContactConfigDetail(generics.RetrieveUpdateAPIView): - permission_classes = [api_permissions.IsAdminUserOrReadOnly] - queryset = models.HelpContactConfig.objects.all() - serializer_class = api_serializers.HelpContactConfigSerializer - - def get_object(self): - obj = shortcuts.get_object_or_404(models.HelpContactConfig) - return obj - - -class ShipmentConfigDetail(generics.RetrieveUpdateAPIView): - permission_classes = [api_permissions.IsAdminUserOrReadOnly] - queryset = models.ShipmentConfig.objects.all() - serializer_class = api_serializers.ShipmentConfigSerializer - - def get_object(self): - obj = shortcuts.get_object_or_404(models.ShipmentConfig) - return obj - -class BatchList(generics.ListCreateAPIView): - filter_backends = [ - rest_framework.DjangoFilterBackend, - rest_framework_filters.OrderingFilter, - rest_framework_filters.SearchFilter, - ] - - filterset_class = api_filters.BatchFilter - ordering_fields = ['created_at', 'updated_at'] - pagination_class = paginations.SmallResultsSetPagination - permission_classes = [rest_framework_permissions.IsAuthenticated] - queryset = models.Batch.objects.all() - schema = schemas.BatchListSchema() - search_fields = ['batch_name'] - serializer_class = api_serializers.BatchSerializer - - def post(self, request, _format=None): - serializer = self.get_serializer(data=request.data) - serializer.is_valid(raise_exception=True) - if serializer.validated_data['start_date'] < serializer.validated_data['end_date']: - batch = models.Batch.objects.create( - batch_name=serializer.validated_data['batch_name'], - start_date=serializer.validated_data['start_date'], - end_date=serializer.validated_data['end_date'], - shipping_cost=serializer.validated_data['shipping_cost'], - ) - else: - raise rest_framework_exceptions.PermissionDenied(_( - 'Start Date must be earlier than End Date.' - )) - return response.Response( - {'id': batch.id}, - status=status.HTTP_201_CREATED - ) - - def filter_queryset(self, queryset): - queryset = super().filter_queryset(queryset) - if not self.request.user.is_staff: - return queryset.filter(user=self.request.user) - return queryset - -class BatchDetail(generics.RetrieveUpdateDestroyAPIView): - permission_classes = [ - api_permissions.IsAdminUserOrReadOnly, - rest_framework_permissions.IsAuthenticated, - ] - queryset = models.Batch.objects.all() - serializer_class = api_serializers.BatchSerializer - -class BatchCreate(rest_framework_views.APIView): - permission_classes = [rest_framework_permissions.IsAuthenticated] - serializer_class = api_serializers.BatchCreateSerializer - - def get_serializer(self, *args, **kwargs): - return self.serializer_class(*args, **kwargs) - - def post(self, request, _format=None): - serializer = self.get_serializer(data=request.data) - serializer.is_valid(raise_exception=True) - - if serializer.validated_data['start_date'] < serializer.validated_date['end_date']: - batch = models.Batch.objects.create( - batch_name=serializer.validated_data['batch_name'], - start_date=serializer.validated_data['start_date'], - end_date=serializer.validated_data['end_date'], - shipping_cost=serializer.validated_data['shipping_cost'], - ) - else: - raise rest_framework_exceptions.PermissionDenied(_( - 'Start Date must be earlier than End Date.' - )) - return response.Response( - {'id': batch.id}, - status=status.HTTP_201_CREATED - ) diff --git a/api/views/__init__.py b/api/views/__init__.py new file mode 100644 index 0000000..612dc85 --- /dev/null +++ b/api/views/__init__.py @@ -0,0 +1,12 @@ +from .auth import * +from .bank import * +from .batch import * +from .cart import * +from .choices import * +from .config import * +from .donation import * +from .product import * +from .program import * +from .report import * +from .transaction import * +from .user import * \ No newline at end of file diff --git a/api/views/auth.py b/api/views/auth.py new file mode 100644 index 0000000..271d323 --- /dev/null +++ b/api/views/auth.py @@ -0,0 +1,95 @@ +from django import http, shortcuts +from django.contrib import auth +from django.db import transaction as db_transaction, utils as db_utils +from django.db.models import deletion +from django.utils import timezone +from django.utils.translation import gettext_lazy as _ +from django_filters import rest_framework +from knox import views as knox_views +from rest_framework import ( + exceptions as rest_framework_exceptions, filters as rest_framework_filters, generics, + permissions as rest_framework_permissions, response, status, views as rest_framework_views +) +from rest_framework.authtoken import serializers as authtoken_serializers +from rest_framework.decorators import api_view +from django.views.decorators.csrf import csrf_exempt +from api import ( + constants, exceptions as api_exceptions, filters as api_filters, models, paginations, + permissions as api_permissions, reports_writer, schemas, serializers as api_serializers, + utils as api_utils +) +from home_industry import utils as home_industry_utils + +class AuthRegister(generics.CreateAPIView): + permission_classes = [api_permissions.IsAnonymousUser] + serializer_class = api_serializers.UserSerializer + + +class AuthCredLogin(knox_views.LoginView): + permission_classes = [rest_framework_permissions.AllowAny] + serializer_class = authtoken_serializers.AuthTokenSerializer + + def get_serializer(self, *args, **kwargs): + return self.serializer_class(*args, **kwargs) + + def post(self, request, format=None): # pylint: disable=redefined-builtin + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + user = serializer.validated_data['user'] + auth.login(request, user) + return super().post(request, format) + + +class AuthPhoneNumberLogin(rest_framework_views.APIView): + permission_classes = [rest_framework_permissions.AllowAny] + serializer_class = api_serializers.PhoneNumberSerializer + + def get_serializer(self, *args, **kwargs): + return self.serializer_class(*args, **kwargs) + + def post(self, request, _format=None): + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + user = shortcuts.get_object_or_404( + models.User, + phone_number=serializer.validated_data['phone_number'] + ) + user.otp = api_utils.generate_otp() + user.save() + api_utils.send_otp(str(user.phone_number), user.otp) + token = api_utils.generate_bearer_token(user) + return response.Response({'token': token}, status=status.HTTP_200_OK) + + +class AuthOTPLogin(knox_views.LoginView): + permission_classes = [rest_framework_permissions.AllowAny] + serializer_class = api_serializers.OTPSerializer + + def get_serializer(self, *args, **kwargs): + return self.serializer_class(*args, **kwargs) + + def post(self, request, format=None): # pylint: disable=redefined-builtin + http_authorization = self.request.META.get('HTTP_AUTHORIZATION') + username = api_utils.get_username_from_bearer_token(http_authorization) + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + user = shortcuts.get_object_or_404(models.User, username=username) + if user.otp != serializer.validated_data['otp']: + return response.Response(status=status.HTTP_400_BAD_REQUEST) + auth.login(request, user) + user.otp = '' + user.save() + return super().post(request, format) + + +class AuthResendOTP(rest_framework_views.APIView): + permission_classes = [rest_framework_permissions.AllowAny] + + def post(self, request, _format=None): + http_authorization = self.request.META.get('HTTP_AUTHORIZATION') + username = api_utils.get_username_from_bearer_token(http_authorization) + user = shortcuts.get_object_or_404(models.User, username=username) + user.otp = api_utils.generate_otp() + user.save() + api_utils.send_otp(str(user.phone_number), user.otp) + return response.Response(status=status.HTTP_204_NO_CONTENT) \ No newline at end of file diff --git a/api/views/bank.py b/api/views/bank.py new file mode 100644 index 0000000..1fc205a --- /dev/null +++ b/api/views/bank.py @@ -0,0 +1,42 @@ +from django import http, shortcuts +from django.contrib import auth +from django.db import transaction as db_transaction, utils as db_utils +from django.db.models import deletion +from django.utils import timezone +from django.utils.translation import gettext_lazy as _ +from django_filters import rest_framework +from knox import views as knox_views +from rest_framework import ( + exceptions as rest_framework_exceptions, filters as rest_framework_filters, generics, + permissions as rest_framework_permissions, response, status, views as rest_framework_views +) +from rest_framework.authtoken import serializers as authtoken_serializers +from rest_framework.decorators import api_view +from django.views.decorators.csrf import csrf_exempt +from api import ( + constants, exceptions as api_exceptions, filters as api_filters, models, paginations, + permissions as api_permissions, reports_writer, schemas, serializers as api_serializers, + utils as api_utils +) +from home_industry import utils as home_industry_utils + +class BankAccountTransferDestinationList(generics.ListCreateAPIView): + filter_backends = [rest_framework_filters.SearchFilter] + pagination_class = paginations.SmallResultsSetPagination + permission_classes = [ + api_permissions.IsAdminUserOrReadOnly, + rest_framework_permissions.IsAuthenticated, + ] + queryset = models.BankAccountTransferDestination.objects.all() + search_fields = ['bank_name', 'bank_account_number', 'bank_account_name'] + serializer_class = api_serializers.BankAccountTransferDestinationSerializer + + +class BankAccountTransferDestinationDetail(generics.RetrieveUpdateDestroyAPIView): + permission_classes = [ + api_permissions.IsAdminUserOrReadOnly, + rest_framework_permissions.IsAuthenticated, + ] + queryset = models.BankAccountTransferDestination.objects.all() + serializer_class = api_serializers.BankAccountTransferDestinationSerializer + diff --git a/api/views/batch.py b/api/views/batch.py new file mode 100644 index 0000000..c6d4c36 --- /dev/null +++ b/api/views/batch.py @@ -0,0 +1,97 @@ +from django import http, shortcuts +from django.contrib import auth +from django.db import transaction as db_transaction, utils as db_utils +from django.db.models import deletion +from django.utils import timezone +from django.utils.translation import gettext_lazy as _ +from django_filters import rest_framework +from knox import views as knox_views +from rest_framework import ( + exceptions as rest_framework_exceptions, filters as rest_framework_filters, generics, + permissions as rest_framework_permissions, response, status, views as rest_framework_views +) +from rest_framework.authtoken import serializers as authtoken_serializers +from rest_framework.decorators import api_view +from django.views.decorators.csrf import csrf_exempt +from api import ( + constants, exceptions as api_exceptions, filters as api_filters, models, paginations, + permissions as api_permissions, reports_writer, schemas, serializers as api_serializers, + utils as api_utils +) +from home_industry import utils as home_industry_utils + +class BatchList(generics.ListCreateAPIView): + filter_backends = [ + rest_framework.DjangoFilterBackend, + rest_framework_filters.OrderingFilter, + rest_framework_filters.SearchFilter, + ] + + filterset_class = api_filters.BatchFilter + ordering_fields = ['created_at', 'updated_at'] + pagination_class = paginations.SmallResultsSetPagination + permission_classes = [rest_framework_permissions.IsAuthenticated] + queryset = models.Batch.objects.all() + schema = schemas.BatchListSchema() + search_fields = ['batch_name'] + serializer_class = api_serializers.BatchSerializer + + def post(self, request, _format=None): + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + if serializer.validated_data['start_date'] < serializer.validated_data['end_date']: + batch = models.Batch.objects.create( + batch_name=serializer.validated_data['batch_name'], + start_date=serializer.validated_data['start_date'], + end_date=serializer.validated_data['end_date'], + shipping_cost=serializer.validated_data['shipping_cost'], + ) + else: + raise rest_framework_exceptions.PermissionDenied(_( + 'Start Date must be earlier than End Date.' + )) + return response.Response( + {'id': batch.id}, + status=status.HTTP_201_CREATED + ) + + def filter_queryset(self, queryset): + queryset = super().filter_queryset(queryset) + if not self.request.user.is_staff: + return queryset.filter(user=self.request.user) + return queryset + +class BatchDetail(generics.RetrieveUpdateDestroyAPIView): + permission_classes = [ + api_permissions.IsAdminUserOrReadOnly, + rest_framework_permissions.IsAuthenticated, + ] + queryset = models.Batch.objects.all() + serializer_class = api_serializers.BatchSerializer + +class BatchCreate(rest_framework_views.APIView): + permission_classes = [rest_framework_permissions.IsAuthenticated] + serializer_class = api_serializers.BatchCreateSerializer + + def get_serializer(self, *args, **kwargs): + return self.serializer_class(*args, **kwargs) + + def post(self, request, _format=None): + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + + if serializer.validated_data['start_date'] < serializer.validated_date['end_date']: + batch = models.Batch.objects.create( + batch_name=serializer.validated_data['batch_name'], + start_date=serializer.validated_data['start_date'], + end_date=serializer.validated_data['end_date'], + shipping_cost=serializer.validated_data['shipping_cost'], + ) + else: + raise rest_framework_exceptions.PermissionDenied(_( + 'Start Date must be earlier than End Date.' + )) + return response.Response( + {'id': batch.id}, + status=status.HTTP_201_CREATED + ) diff --git a/api/views/cart.py b/api/views/cart.py new file mode 100644 index 0000000..2198acf --- /dev/null +++ b/api/views/cart.py @@ -0,0 +1,249 @@ +from django import http, shortcuts +from django.contrib import auth +from django.db import transaction as db_transaction, utils as db_utils +from django.db.models import deletion +from django.utils import timezone +from django.utils.translation import gettext_lazy as _ +from django_filters import rest_framework +from knox import views as knox_views +from rest_framework import ( + exceptions as rest_framework_exceptions, filters as rest_framework_filters, generics, + permissions as rest_framework_permissions, response, status, views as rest_framework_views +) +from rest_framework.authtoken import serializers as authtoken_serializers +from rest_framework.decorators import api_view +from django.views.decorators.csrf import csrf_exempt +from api import ( + constants, exceptions as api_exceptions, filters as api_filters, models, paginations, + permissions as api_permissions, reports_writer, schemas, serializers as api_serializers, + utils as api_utils +) +from home_industry import utils as home_industry_utils + +class CartUpdate(rest_framework_views.APIView): + permission_classes = [rest_framework_permissions.IsAuthenticated] + serializer_class = api_serializers.CartUpdateSerializer + + def get_serializer(self, *args, **kwargs): + return self.serializer_class(*args, **kwargs) + + def post(self, request, _format=None): + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + user = request.user + product = shortcuts.get_object_or_404( + models.Product, + id=serializer.validated_data['product'] + ) + shopping_cart = models.ShoppingCart.objects.get(user=user) + cart_item, _created = models.CartItem.objects.get_or_create( + product=product, + shopping_cart=shopping_cart + ) + if serializer.validated_data['quantity'] == 0: + cart_item.delete() + else: + cart_item.quantity = serializer.validated_data['quantity'] + cart_item.save() + return response.Response(status=status.HTTP_204_NO_CONTENT) + + +class CartOverview(rest_framework_views.APIView): + permission_classes = [rest_framework_permissions.IsAuthenticated] + + def get(self, request, _format=None): + user = request.user + shopping_cart = models.ShoppingCart.objects.get(user=user) + item_subtotal = sum( + cart_item.product.price * cart_item.quantity + for cart_item in shopping_cart.cart_items.all() + ) + shipping_costs = api_utils.get_shipping_costs(user) + if shipping_costs is None: + return response.Response( + {'item_subtotal': str(item_subtotal)}, + status=status.HTTP_200_OK + ) + return response.Response( + {'item_subtotal': str(item_subtotal), 'shipping_costs': str(shipping_costs)}, + status=status.HTTP_200_OK + ) + + +class CartCheckout(rest_framework_views.APIView): + permission_classes = [rest_framework_permissions.IsAuthenticated] + serializer_class = api_serializers.CartCheckoutSerializer + + def get_serializer(self, *args, **kwargs): + return self.serializer_class(*args, **kwargs) + + def post(self, request, _format=None): + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + user = request.user + shipment_config = home_industry_utils.get_shipment_config() + if user.sub_district.lower() != shipment_config.sub_district.lower(): + raise rest_framework_exceptions.ParseError(_( # pylint: disable=no-member + 'Cannot process shipment to other sub-districts other than {sub_district}.' + ).format(sub_district=shipment_config.sub_district)) + shopping_cart = models.ShoppingCart.objects.get(user=user) + cart_items = shopping_cart.cart_items.all() + if not cart_items.exists(): + raise rest_framework_exceptions.ParseError(_( + 'Unable to checkout because there are no items purchased.' + )) + api_utils.validate_product_stock(cart_items) + transaction_status = ( + '001' if serializer.validated_data['payment_method'] == 'TRF' else '002' + ) + + transaction = models.Transaction.objects.create( + user=user, + payment_method=serializer.validated_data['payment_method'], + donation=serializer.validated_data['donation'], + transaction_status=transaction_status, + batch = ( + None if serializer.validated_data['payment_method'] == 'TRF' + else models.Batch.objects.filter( + start_date__lte=timezone.now().date(), + end_date__gte=timezone.now().date()).first() + ) + ) + + is_success = True + for cart_item in cart_items: + product = cart_item.product + if product.stock is not None: + try: + with db_transaction.atomic(): + product.stock -= cart_item.quantity + product.total_profit += cart_item.quantity*product.profit + product.save() + except db_utils.IntegrityError: + is_success = False + models.TransactionItem.objects.create( + transaction=transaction, + product=product, + quantity=cart_item.quantity + ) + cart_item.delete() + if not is_success: + transaction.transaction_status = '007' + transaction.save() + raise rest_framework_exceptions.APIException(_('Checkout failed.')) + return response.Response({'transaction': transaction.id}, status=status.HTTP_200_OK) + + +class CartUploadPOP(rest_framework_views.APIView): + permission_classes = [rest_framework_permissions.IsAuthenticated] + serializer_class = api_serializers.CartUploadPOPSerializer + + def get_serializer(self, *args, **kwargs): + return self.serializer_class(*args, **kwargs) + + def post(self, request, _format=None): + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + user = request.user + bank_account_transfer_destination = shortcuts.get_object_or_404( + models.BankAccountTransferDestination, + id=serializer.validated_data['bank_account_transfer_destination'] + ) + transaction = shortcuts.get_object_or_404( + models.Transaction, + id=serializer.validated_data['transaction'], + user=user + ) + if transaction.payment_method != 'TRF': + raise rest_framework_exceptions.PermissionDenied(_( + 'The payment method for this transaction is not a transfer.' + )) + if transaction.transaction_status not in ('001', '002'): + raise rest_framework_exceptions.PermissionDenied(_( + 'Cannot upload proof of payment at this stage.' + )) + transaction.proof_of_payment = serializer.validated_data['proof_of_payment'] + transaction.user_bank_name = serializer.validated_data['user_bank_name'] + transaction.user_bank_account_name = serializer.validated_data['user_bank_account_name'] + transaction.bank_account_transfer_destination = bank_account_transfer_destination + transaction.update_bank_account_transfer_destination = True + transaction.transaction_status = '002' + transaction.batch = models.Batch.objects.filter( + start_date__lte=timezone.now().date(), + end_date__gte=timezone.now().date()).first() + transaction.save() + return response.Response(status=status.HTTP_204_NO_CONTENT) + + +class CartCompleteTransaction(rest_framework_views.APIView): + permission_classes = [rest_framework_permissions.IsAuthenticated] + serializer_class = api_serializers.CartCompleteOrCancelTransactionSerializer + + def get_serializer(self, *args, **kwargs): + return self.serializer_class(*args, **kwargs) + + def post(self, request, _format=None): + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + transaction = shortcuts.get_object_or_404( + models.Transaction, + id=serializer.validated_data['transaction'], + user=request.user + ) + if transaction.transaction_status != '004': + raise rest_framework_exceptions.PermissionDenied(_( + 'Transaction cannot be completed unless the status is "Being shipped".' + )) + transaction.transaction_status = '005' + transaction.save() + return response.Response(status=status.HTTP_204_NO_CONTENT) + + +class CartCancelTransaction(rest_framework_views.APIView): + permission_classes = [rest_framework_permissions.IsAuthenticated] + serializer_class = api_serializers.CartCompleteOrCancelTransactionSerializer + + def get_serializer(self, *args, **kwargs): + return self.serializer_class(*args, **kwargs) + + def post(self, request, _format=None): + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + user = request.user + transaction = shortcuts.get_object_or_404( + models.Transaction, + id=serializer.validated_data['transaction'], + user=user + ) + if transaction.transaction_status not in ('001', '002'): + raise rest_framework_exceptions.PermissionDenied(_( + 'Transaction cannot be canceled at this stage.' + )) + transaction_items = transaction.transaction_items.all() + api_utils.return_transaction_items_to_product_stock(transaction_items) + transaction.transaction_status = '006' + transaction.save() + return response.Response(status=status.HTTP_204_NO_CONTENT) + + +class ShoppingCartList(generics.ListAPIView): + filter_backends = [rest_framework.DjangoFilterBackend] + filterset_fields = ['user'] + pagination_class = paginations.SmallResultsSetPagination + permission_classes = [rest_framework_permissions.IsAdminUser] + queryset = models.ShoppingCart.objects.all() + serializer_class = api_serializers.ShoppingCartSerializer + + +class ShoppingCartDetail(generics.RetrieveAPIView): + permission_classes = [ + api_permissions.IsAdminUserOrOwner, + rest_framework_permissions.IsAuthenticated, + ] + queryset = models.ShoppingCart.objects.all() + serializer_class = api_serializers.ShoppingCartSerializer + + def get_object(self): + if self.kwargs.get('pk') == 'self': + self.kwargs['pk'] = models.ShoppingCart.objects.get(user=self.request.user).id + return super().get_object() diff --git a/api/views/choices.py b/api/views/choices.py new file mode 100644 index 0000000..d18e300 --- /dev/null +++ b/api/views/choices.py @@ -0,0 +1,43 @@ +from django import http, shortcuts +from django.contrib import auth +from django.db import transaction as db_transaction, utils as db_utils +from django.db.models import deletion +from django.utils import timezone +from django.utils.translation import gettext_lazy as _ +from django_filters import rest_framework +from knox import views as knox_views +from rest_framework import ( + exceptions as rest_framework_exceptions, filters as rest_framework_filters, generics, + permissions as rest_framework_permissions, response, status, views as rest_framework_views +) +from rest_framework.authtoken import serializers as authtoken_serializers +from rest_framework.decorators import api_view +from django.views.decorators.csrf import csrf_exempt +from api import ( + constants, exceptions as api_exceptions, filters as api_filters, models, paginations, + permissions as api_permissions, reports_writer, schemas, serializers as api_serializers, + utils as api_utils +) +from home_industry import utils as home_industry_utils + +class ChoicesAPIView(rest_framework_views.APIView): + choices = None + permission_classes = [rest_framework_permissions.IsAuthenticated] + + def get(self, request, _format=None): + assert self.choices is not None, ( + '{} should include a `choices` attribute.'.format(self.__class__.__name__) + ) + return response.Response(api_utils.map_choices(self.choices), status=status.HTTP_200_OK) + + +class PaymentMethodChoices(ChoicesAPIView): + choices = constants.PAYMENT_METHOD_CHOICES + + +class TransactionStatusChoices(ChoicesAPIView): + choices = constants.TRANSACTION_STATUS_CHOICES + + +class DonationStatusChoices(ChoicesAPIView): + choices = constants.DONATION_STATUS_CHOICES diff --git a/api/views/config.py b/api/views/config.py new file mode 100644 index 0000000..312807a --- /dev/null +++ b/api/views/config.py @@ -0,0 +1,50 @@ +from django import http, shortcuts +from django.contrib import auth +from django.db import transaction as db_transaction, utils as db_utils +from django.db.models import deletion +from django.utils import timezone +from django.utils.translation import gettext_lazy as _ +from django_filters import rest_framework +from knox import views as knox_views +from rest_framework import ( + exceptions as rest_framework_exceptions, filters as rest_framework_filters, generics, + permissions as rest_framework_permissions, response, status, views as rest_framework_views +) +from rest_framework.authtoken import serializers as authtoken_serializers +from rest_framework.decorators import api_view +from django.views.decorators.csrf import csrf_exempt +from api import ( + constants, exceptions as api_exceptions, filters as api_filters, models, paginations, + permissions as api_permissions, reports_writer, schemas, serializers as api_serializers, + utils as api_utils +) +from home_industry import utils as home_industry_utils + +class AppConfigDetail(generics.RetrieveUpdateAPIView): + permission_classes = [rest_framework_permissions.IsAdminUser] + queryset = models.AppConfig.objects.all() + serializer_class = api_serializers.AppConfigSerializer + + def get_object(self): + obj = shortcuts.get_object_or_404(models.AppConfig) + return obj + + +class HelpContactConfigDetail(generics.RetrieveUpdateAPIView): + permission_classes = [api_permissions.IsAdminUserOrReadOnly] + queryset = models.HelpContactConfig.objects.all() + serializer_class = api_serializers.HelpContactConfigSerializer + + def get_object(self): + obj = shortcuts.get_object_or_404(models.HelpContactConfig) + return obj + + +class ShipmentConfigDetail(generics.RetrieveUpdateAPIView): + permission_classes = [api_permissions.IsAdminUserOrReadOnly] + queryset = models.ShipmentConfig.objects.all() + serializer_class = api_serializers.ShipmentConfigSerializer + + def get_object(self): + obj = shortcuts.get_object_or_404(models.ShipmentConfig) + return obj diff --git a/api/views/donation.py b/api/views/donation.py new file mode 100644 index 0000000..f395df1 --- /dev/null +++ b/api/views/donation.py @@ -0,0 +1,128 @@ +from django import http, shortcuts +from django.contrib import auth +from django.db import transaction as db_transaction, utils as db_utils +from django.db.models import deletion +from django.utils import timezone +from django.utils.translation import gettext_lazy as _ +from django_filters import rest_framework +from knox import views as knox_views +from rest_framework import ( + exceptions as rest_framework_exceptions, filters as rest_framework_filters, generics, + permissions as rest_framework_permissions, response, status, views as rest_framework_views +) +from rest_framework.authtoken import serializers as authtoken_serializers +from rest_framework.decorators import api_view +from django.views.decorators.csrf import csrf_exempt +from api import ( + constants, exceptions as api_exceptions, filters as api_filters, models, paginations, + permissions as api_permissions, reports_writer, schemas, serializers as api_serializers, + utils as api_utils +) +from home_industry import utils as home_industry_utils + +class DonationCreate(rest_framework_views.APIView): + permission_classes = [rest_framework_permissions.IsAuthenticated] + serializer_class = api_serializers.DonationCreateSerializer + + def get_serializer(self, *args, **kwargs): + return self.serializer_class(*args, **kwargs) + + def post(self, request, _format=None): + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + user = request.user + program = shortcuts.get_object_or_404( + models.Program, + id=serializer.validated_data['program'] + ) + if not program.open_donation: + raise rest_framework_exceptions.PermissionDenied(_( + 'This program is currently not accepting donations.' + )) + program_donation = None + if serializer.validated_data['donation_type'] == 'CSH': + bank_account_transfer_destination = shortcuts.get_object_or_404( + models.BankAccountTransferDestination, + id=serializer.validated_data['bank_account_transfer_destination'] + ) + program_donation = models.ProgramDonation.objects.create( + user=user, + program=program, + donation_type='CSH', + amount=serializer.validated_data['amount'], + proof_of_bank_transfer=serializer.validated_data['proof_of_bank_transfer'], + user_bank_name=serializer.validated_data['user_bank_name'], + user_bank_account_name=serializer.validated_data['user_bank_account_name'], + bank_account_transfer_destination=bank_account_transfer_destination + ) + + else: + if serializer.validated_data['delivery_method'] == 'DLV': + program_donation = models.ProgramDonation.objects.create( + user=user, + program=program, + donation_type='GDS', + goods_quantity=serializer.validated_data['goods_quantity'], + goods_description=serializer.validated_data['goods_description'], + delivery_method=serializer.validated_data['delivery_method'], + delivery_address=None + ) + else: + program_donation = models.ProgramDonation.objects.create( + user=user, + program=program, + donation_type='GDS', + goods_quantity=serializer.validated_data['goods_quantity'], + goods_description=serializer.validated_data['goods_description'], + delivery_method=serializer.validated_data['delivery_method'], + delivery_address=serializer.validated_data['delivery_address'] + ) + + return response.Response( + {'program_donation': program_donation.id}, + status=status.HTTP_200_OK + ) + + + +class DonationReuploadProofOfBankTransfer(rest_framework_views.APIView): + permission_classes = [rest_framework_permissions.IsAuthenticated] + serializer_class = api_serializers.DonationReuploadProofOfBankTransferSerializer + + def get_serializer(self, *args, **kwargs): + return self.serializer_class(*args, **kwargs) + + def post(self, request, _format=None): + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + user = request.user + bank_account_transfer_destination = shortcuts.get_object_or_404( + models.BankAccountTransferDestination, + id=serializer.validated_data['bank_account_transfer_destination'] + ) + program_donation = shortcuts.get_object_or_404( + models.ProgramDonation, + id=serializer.validated_data['program_donation'], + user=user + ) + if program_donation.donation_status not in ('001', '004'): + raise rest_framework_exceptions.PermissionDenied(_( + 'Cannot reupload proof of bank transfer at this stage.' + )) + if program_donation.donation_type != 'CSH': + raise rest_framework_exceptions.PermissionDenied(_( + 'Cannot proof of bank transfer foor good donation.' + )) + program_donation.amount = serializer.validated_data['amount'] + program_donation.proof_of_bank_transfer = ( + serializer.validated_data['proof_of_bank_transfer'] + ) + program_donation.user_bank_name = serializer.validated_data['user_bank_name'] + program_donation.user_bank_account_name = ( + serializer.validated_data['user_bank_account_name'] + ) + program_donation.bank_account_transfer_destination = bank_account_transfer_destination + program_donation.update_bank_account_transfer_destination = True + program_donation.donation_status = '001' + program_donation.save() + return response.Response(status=status.HTTP_204_NO_CONTENT) diff --git a/api/views/product.py b/api/views/product.py new file mode 100644 index 0000000..3a309ca --- /dev/null +++ b/api/views/product.py @@ -0,0 +1,194 @@ +from django import http, shortcuts +from django.contrib import auth +from django.db import transaction as db_transaction, utils as db_utils +from django.db.models import deletion +from django.utils import timezone +from django.utils.translation import gettext_lazy as _ +from django_filters import rest_framework +from knox import views as knox_views +from rest_framework import ( + exceptions as rest_framework_exceptions, filters as rest_framework_filters, generics, + permissions as rest_framework_permissions, response, status, views as rest_framework_views +) +from rest_framework.authtoken import serializers as authtoken_serializers +from rest_framework.decorators import api_view +from django.views.decorators.csrf import csrf_exempt +from api import ( + constants, exceptions as api_exceptions, filters as api_filters, models, paginations, + permissions as api_permissions, reports_writer, schemas, serializers as api_serializers, + utils as api_utils +) +from home_industry import utils as home_industry_utils + +class CategoryList(generics.ListCreateAPIView): + filter_backends = [ + rest_framework.DjangoFilterBackend, + rest_framework_filters.OrderingFilter, + rest_framework_filters.SearchFilter, + ] + filterset_fields = ['name'] + ordering_fields = ['name'] + pagination_class = paginations.SmallResultsSetPagination + permission_classes = [ + api_permissions.IsAdminUserOrReadOnly, + rest_framework_permissions.IsAuthenticated, + ] + queryset = models.Category.objects.all() + search_fields = ['name'] + serializer_class = api_serializers.CategorySerializer + + +class CategoryDetail(generics.RetrieveUpdateDestroyAPIView): + permission_classes = [ + api_permissions.IsAdminUserOrReadOnly, + rest_framework_permissions.IsAuthenticated, + ] + queryset = models.Category.objects.all() + serializer_class = api_serializers.CategorySerializer + + def destroy(self, request, *_args, **_kwargs): + instance = self.get_object() + try: + instance.delete() + except deletion.ProtectedError: + raise api_exceptions.IntegrityError(_( + 'Cannot delete category due to integrity error.' + )) + return response.Response(status=status.HTTP_204_NO_CONTENT) + + +class SubcategoryList(generics.ListCreateAPIView): + filter_backends = [ + rest_framework.DjangoFilterBackend, + rest_framework_filters.OrderingFilter, + rest_framework_filters.SearchFilter, + ] + filterset_fields = ['name', 'category'] + ordering_fields = ['name'] + pagination_class = paginations.SmallResultsSetPagination + permission_classes = [ + api_permissions.IsAdminUserOrReadOnly, + rest_framework_permissions.IsAuthenticated, + ] + queryset = models.Subcategory.objects.all() + search_fields = ['name'] + serializer_class = api_serializers.SubcategorySerializer + + +class SubcategoryDetail(generics.RetrieveUpdateDestroyAPIView): + permission_classes = [ + api_permissions.IsAdminUserOrReadOnly, + rest_framework_permissions.IsAuthenticated, + ] + queryset = models.Subcategory.objects.all() + serializer_class = api_serializers.SubcategorySerializer + + def destroy(self, request, *_args, **_kwargs): + instance = self.get_object() + try: + instance.delete() + except deletion.ProtectedError: + raise api_exceptions.IntegrityError(_( + 'Cannot delete subcategory due to integrity error.' + )) + return response.Response(status=status.HTTP_204_NO_CONTENT) + + +class ProductList(generics.ListCreateAPIView): + filter_backends = [ + rest_framework.DjangoFilterBackend, + rest_framework_filters.OrderingFilter, + rest_framework_filters.SearchFilter, + ] + filterset_fields = ['code', 'subcategory', 'subcategory__category'] + ordering_fields = ['name', 'price', 'stock'] + pagination_class = paginations.SmallResultsSetPagination + permission_classes = [ + api_permissions.IsAdminUserOrReadOnly, + rest_framework_permissions.IsAuthenticated, + ] + queryset = models.Product.objects.all() + search_fields = ['code', 'name'] + serializer_class = api_serializers.ProductSerializer + + def post(self, request, _format=None): + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + validated_image = None + try: + validated_image = serializer.validated_data['image'] + except KeyError: + pass + product = models.Product.objects.create( + name=serializer.validated_data['name'], + description=serializer.validated_data['description'], + price=serializer.validated_data['price'], + stock=serializer.validated_data['stock'], + modal=serializer.validated_data['modal'], + subcategory=models.Subcategory.objects.get(name=serializer.validated_data['subcategory']), + total_profit=0, + unit=serializer.validated_data['unit'], + image=validated_image + ) + product.profit= (product.price - product.modal) + product.save() + return response.Response( + {'id': product.id}, + status=status.HTTP_201_CREATED + ) + + + +class ProductDetail(generics.RetrieveUpdateDestroyAPIView): + permission_classes = [ + api_permissions.IsAdminUserOrReadOnly, + rest_framework_permissions.IsAuthenticated, + ] + queryset = models.Product.objects.all() + serializer_class = api_serializers.ProductSerializer + + def get_serializer(self, *args, **kwargs): + # leave this intact + serializer_class = self.get_serializer_class() + kwargs["context"] = self.get_serializer_context() + + + + if (self.request != None): + if (self.request.data.get("price") != None) and (self.request.data.get("modal") != None): + draft_request_data = self.request.data.copy() + profit= int(self.request.data['price'])-int(self.request.data['modal']) + new_profit={'profit': profit} + draft_request_data.update(new_profit) + kwargs["data"] = draft_request_data + return serializer_class(*args, **kwargs) + else: + if (self.request.data.get("price") != None): + + instance=self.get_object() + draft_request_data = self.request.data.copy() + profit= int(self.request.data['price'])-int(instance.modal) + new_profit={'profit': profit} + draft_request_data.update(new_profit) + + kwargs["data"] = draft_request_data + return serializer_class(*args, **kwargs) + elif (self.request.data.get("modal") != None): + instance=self.get_object() + draft_request_data = self.request.data.copy() + profit= int(instance.price)-int(self.request.data['modal']) + new_profit={'profit': profit} + draft_request_data.update(new_profit) + + kwargs["data"] = draft_request_data + return serializer_class(*args, **kwargs) + + return serializer_class(*args, **kwargs) + + def partial_update(self, request, *args, **kwargs): + instance = self.get_object() + + serializer = self.get_serializer(instance,data=request.data, partial=True) + serializer.is_valid(raise_exception=True) + + return super().partial_update(request, *args, **kwargs) # pylint: disable=no-member diff --git a/api/views/program.py b/api/views/program.py new file mode 100644 index 0000000..db16210 --- /dev/null +++ b/api/views/program.py @@ -0,0 +1,159 @@ +from django import http, shortcuts +from django.contrib import auth +from django.db import transaction as db_transaction, utils as db_utils +from django.db.models import deletion +from django.utils import timezone +from django.utils.translation import gettext_lazy as _ +from django_filters import rest_framework +from knox import views as knox_views +from rest_framework import ( + exceptions as rest_framework_exceptions, filters as rest_framework_filters, generics, + permissions as rest_framework_permissions, response, status, views as rest_framework_views +) +from rest_framework.authtoken import serializers as authtoken_serializers +from rest_framework.decorators import api_view +from django.views.decorators.csrf import csrf_exempt +from api import ( + constants, exceptions as api_exceptions, filters as api_filters, models, paginations, + permissions as api_permissions, reports_writer, schemas, serializers as api_serializers, + utils as api_utils +) +from home_industry import utils as home_industry_utils + +class ProgramProgressList(generics.ListCreateAPIView): + permission_classes = [ + api_permissions.IsAdminUserOrReadOnly, + rest_framework_permissions.IsAuthenticated, + ] + lookup_field = 'program' + serializer_class = api_serializers.ProgramProgressSerializer + + def get_queryset(self): + return models.ProgramProgress.objects.filter(program=self.get_program()) + + def perform_create(self, serializer): + serializer.save(program=self.get_program()) + + def get_program(self): + program = models.Program.objects.filter(id=self.kwargs.get(self.lookup_field)).first() + if program is None: + raise rest_framework_exceptions.NotFound(_( + 'Program not found.' + )) + return program + +class ProgramList(generics.ListCreateAPIView): + filter_backends = [ + rest_framework.DjangoFilterBackend, + rest_framework_filters.OrderingFilter, + rest_framework_filters.SearchFilter, + ] + filterset_fields = ['code'] + ordering_fields = ['name', 'start_date_time', 'end_date_time'] + pagination_class = paginations.SmallResultsSetPagination + permission_classes = [ + api_permissions.IsAdminUserOrReadOnly, + rest_framework_permissions.IsAuthenticated, + ] + queryset = models.Program.objects.all() + search_fields = ['code', 'name'] + serializer_class = api_serializers.ProgramSerializer + + +class ProgramDetail(generics.RetrieveUpdateDestroyAPIView): + permission_classes = [ + api_permissions.IsAdminUserOrReadOnly, + rest_framework_permissions.IsAuthenticated, + ] + queryset = models.Program.objects.all() + serializer_class = api_serializers.ProgramSerializer + +class ProgramDonationList(generics.ListAPIView): + filter_backends = [ + rest_framework.DjangoFilterBackend, + rest_framework_filters.OrderingFilter, + rest_framework_filters.SearchFilter, + ] + filterset_class = api_filters.ProgramDonationFilter + ordering_fields = ['created_at', 'updated_at'] + pagination_class = paginations.SmallResultsSetPagination + permission_classes = [rest_framework_permissions.IsAuthenticated] + queryset = models.ProgramDonation.objects.all() + schema = schemas.ProgramDonationListSchema() + search_fields = ['donation_number', 'user_full_name', 'program_name', 'donation_type'] + serializer_class = api_serializers.ProgramDonationSerializer + + def filter_queryset(self, queryset): + queryset = super().filter_queryset(queryset) + if not self.request.user.is_staff: + return queryset.filter(user=self.request.user) + return queryset + +@api_view(['DELETE']) +@csrf_exempt +def delete_donation_by_program(request, pid): + if ((request.user) and (request.user.is_staff)): + program = models.Program.objects.get(id=pid) + donation = models.ProgramDonation.objects.filter(program=program) + donation.delete() + return response.Response(status=status.HTTP_204_NO_CONTENT) + +class ProgramDonationListCSH(generics.ListAPIView): + filter_backends = [ + rest_framework.DjangoFilterBackend, + rest_framework_filters.OrderingFilter, + rest_framework_filters.SearchFilter, + ] + filterset_class = api_filters.ProgramDonationFilter + ordering_fields = ['created_at', 'updated_at'] + pagination_class = paginations.SmallResultsSetPagination + permission_classes = [rest_framework_permissions.IsAuthenticated] + queryset = models.ProgramDonation.objects.filter(donation_type='CSH') + schema = schemas.ProgramDonationListSchema() + search_fields = ['donation_number', 'user_full_name', 'program_name', 'donation_type'] + serializer_class = api_serializers.ProgramDonationSerializer + + def filter_queryset(self, queryset): + queryset = super().filter_queryset(queryset) + if not self.request.user.is_staff: + return queryset.filter(user=self.request.user) + return queryset + +class ProgramDonationListGDS(generics.ListAPIView): + filter_backends = [ + rest_framework.DjangoFilterBackend, + rest_framework_filters.OrderingFilter, + rest_framework_filters.SearchFilter, + ] + filterset_class = api_filters.ProgramDonationFilter + ordering_fields = ['created_at', 'updated_at'] + pagination_class = paginations.SmallResultsSetPagination + permission_classes = [rest_framework_permissions.IsAuthenticated] + queryset = models.ProgramDonation.objects.filter(donation_type='GDS') + schema = schemas.ProgramDonationListSchema() + search_fields = ['donation_number', 'user_full_name', 'program_name', 'donation_type'] + serializer_class = api_serializers.ProgramDonationSerializer + + def filter_queryset(self, queryset): + queryset = super().filter_queryset(queryset) + if not self.request.user.is_staff: + return queryset.filter(user=self.request.user) + return queryset + +class ProgramDonationDetail(generics.RetrieveUpdateAPIView): + permission_classes = [ + api_permissions.IsAdminUserOrOwnerReadOnly, + rest_framework_permissions.IsAuthenticated, + ] + queryset = models.ProgramDonation.objects.all() + serializer_class = api_serializers.ProgramDonationSerializer + + def update(self, request, *args, **kwargs): + instance = self.get_object() + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + if instance.donation_status in ('002', '003'): + raise rest_framework_exceptions.PermissionDenied(_( + 'Cannot update program donation because it has a completed or canceled status.' + )) + return super().update(request, *args, **kwargs) # pylint: disable=no-member diff --git a/api/views/report.py b/api/views/report.py new file mode 100644 index 0000000..7d3e52e --- /dev/null +++ b/api/views/report.py @@ -0,0 +1,90 @@ +from django import http, shortcuts +from django.contrib import auth +from django.db import transaction as db_transaction, utils as db_utils +from django.db.models import deletion +from django.utils import timezone +from django.utils.translation import gettext_lazy as _ +from django_filters import rest_framework +from knox import views as knox_views +from rest_framework import ( + exceptions as rest_framework_exceptions, filters as rest_framework_filters, generics, + permissions as rest_framework_permissions, response, status, views as rest_framework_views +) +from rest_framework.authtoken import serializers as authtoken_serializers +from rest_framework.decorators import api_view +from django.views.decorators.csrf import csrf_exempt +from api import ( + constants, exceptions as api_exceptions, filters as api_filters, models, paginations, + permissions as api_permissions, reports_writer, schemas, serializers as api_serializers, + utils as api_utils +) +from home_industry import utils as home_industry_utils + +class ReportAPIView(rest_framework_views.APIView): + permission_classes = [rest_framework_permissions.IsAdminUser] + report_function = None + serializer_class = None + + def get_filename(self, query_params): + raise NotImplementedError + + def get_serializer(self, *args, **kwargs): + return self.serializer_class(*args, **kwargs) # pylint: disable=not-callable + + def get(self, request, _format=None): + assert self.report_function is not None, ( + '{} should include a `report_function` attribute.'.format(self.__class__.__name__) + ) + assert self.report_function is not None, ( + '{} should include a `serializer_class` attribute.'.format(self.__class__.__name__) + ) + serializer = self.get_serializer(data=request.query_params) + serializer.is_valid(raise_exception=True) + buffer = self.report_function.__func__(serializer.validated_data) + buffer.seek(0) + return http.FileResponse(buffer, filename=self.get_filename(serializer.validated_data)) + + +class ReportTransaction(ReportAPIView): + report_function = reports_writer.create_transaction_report + schema = schemas.ReportTransactionSchema() + serializer_class = api_serializers.ReportTransactionSerializer + + def get_filename(self, query_params): + filename = '{}.xlsx'.format(_( # pylint: disable=no-member + 'Transaction Report from {date_from} to {date_to} for {batch_name}' + ).format( + date_from=query_params.get('created_at_date_range_after', '_'), + date_to=query_params.get('created_at_date_range_before', str(timezone.now())[:10]), + batch_name=query_params.get('batch_name', '_') + )) + return filename + + +class ReportProgramDonationCSH(ReportAPIView): + report_function = reports_writer.create_program_donation_report_csh + schema = schemas.ReportProgramDonationSchema() + serializer_class = api_serializers.ReportProgramDonationSerializer + + def get_filename(self, query_params): + filename = '{}.xlsx'.format(_( # pylint: disable=no-member + 'Program Donation Report from {date_from} to {date_to}' + ).format( + date_from=query_params.get('created_at_date_range_after', '_'), + date_to=query_params.get('created_at_date_range_before', str(timezone.now())[:10]) + )) + return filename + +class ReportProgramDonationGDS(ReportAPIView): + report_function = reports_writer.create_program_donation_report_gds + schema = schemas.ReportProgramDonationSchema() + serializer_class = api_serializers.ReportProgramDonationSerializer + + def get_filename(self, query_params): + filename = '{}.xlsx'.format(_( # pylint: disable=no-member + 'Program Donation Report from {date_from} to {date_to}' + ).format( + date_from=query_params.get('created_at_date_range_after', '_'), + date_to=query_params.get('created_at_date_range_before', str(timezone.now())[:10]) + )) + return filename \ No newline at end of file diff --git a/api/views/transaction.py b/api/views/transaction.py new file mode 100644 index 0000000..0833808 --- /dev/null +++ b/api/views/transaction.py @@ -0,0 +1,64 @@ +from django import http, shortcuts +from django.contrib import auth +from django.db import transaction as db_transaction, utils as db_utils +from django.db.models import deletion +from django.utils import timezone +from django.utils.translation import gettext_lazy as _ +from django_filters import rest_framework +from knox import views as knox_views +from rest_framework import ( + exceptions as rest_framework_exceptions, filters as rest_framework_filters, generics, + permissions as rest_framework_permissions, response, status, views as rest_framework_views +) +from rest_framework.authtoken import serializers as authtoken_serializers +from rest_framework.decorators import api_view +from django.views.decorators.csrf import csrf_exempt +from api import ( + constants, exceptions as api_exceptions, filters as api_filters, models, paginations, + permissions as api_permissions, reports_writer, schemas, serializers as api_serializers, + utils as api_utils +) +from home_industry import utils as home_industry_utils + +class TransactionList(generics.ListAPIView): + filter_backends = [ + rest_framework.DjangoFilterBackend, + rest_framework_filters.OrderingFilter, + rest_framework_filters.SearchFilter, + ] + filterset_class = api_filters.TransactionFilter + ordering_fields = ['created_at', 'updated_at'] + pagination_class = paginations.SmallResultsSetPagination + permission_classes = [rest_framework_permissions.IsAuthenticated] + queryset = models.Transaction.objects.all() + schema = schemas.TransactionListSchema() + search_fields = ['transaction_number', 'user_full_name'] + serializer_class = api_serializers.TransactionSerializer + + def filter_queryset(self, queryset): + queryset = super().filter_queryset(queryset) + if not self.request.user.is_staff: + return queryset.filter(user=self.request.user) + return queryset + + +class TransactionDetail(generics.RetrieveUpdateAPIView): + permission_classes = [ + api_permissions.IsAdminUserOrOwnerReadOnly, + rest_framework_permissions.IsAuthenticated, + ] + queryset = models.Transaction.objects.all() + serializer_class = api_serializers.TransactionSerializer + + def update(self, request, *args, **kwargs): + instance = self.get_object() + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + if instance.transaction_status in ('005', '006', '007'): + raise rest_framework_exceptions.PermissionDenied(_( + 'Cannot update transaction because it has a completed, canceled, or failed status.' + )) + if serializer.validated_data['transaction_status'] == '006': + transaction_items = instance.transaction_items.all() + api_utils.return_transaction_items_to_product_stock(transaction_items) + return super().update(request, *args, **kwargs) # pylint: disable=no-member diff --git a/api/views/user.py b/api/views/user.py new file mode 100644 index 0000000..4609737 --- /dev/null +++ b/api/views/user.py @@ -0,0 +1,51 @@ +from django import http, shortcuts +from django.contrib import auth +from django.db import transaction as db_transaction, utils as db_utils +from django.db.models import deletion +from django.utils import timezone +from django.utils.translation import gettext_lazy as _ +from django_filters import rest_framework +from knox import views as knox_views +from rest_framework import ( + exceptions as rest_framework_exceptions, filters as rest_framework_filters, generics, + permissions as rest_framework_permissions, response, status, views as rest_framework_views +) +from rest_framework.authtoken import serializers as authtoken_serializers +from rest_framework.decorators import api_view +from django.views.decorators.csrf import csrf_exempt +from api import ( + constants, exceptions as api_exceptions, filters as api_filters, models, paginations, + permissions as api_permissions, reports_writer, schemas, serializers as api_serializers, + utils as api_utils +) +from home_industry import utils as home_industry_utils + +class UserList(generics.ListCreateAPIView): + filter_backends = [ + rest_framework.DjangoFilterBackend, + rest_framework_filters.OrderingFilter, + rest_framework_filters.SearchFilter, + ] + filterset_fields = ['username', 'phone_number'] + ordering_fields = [ + 'username', 'full_name', 'phone_number', + 'total_transactions', 'total_program_donations_goods', 'total_program_donations_cash' + ] + pagination_class = paginations.SmallResultsSetPagination + permission_classes = [rest_framework_permissions.IsAdminUser] + queryset = models.User.objects.all() + search_fields = ['username', 'full_name', 'phone_number'] + serializer_class = api_serializers.UserSerializer + +class UserDetail(generics.RetrieveUpdateDestroyAPIView): + permission_classes = [ + api_permissions.IsAdminUserOrSelf, + rest_framework_permissions.IsAuthenticated, + ] + queryset = models.User.objects.all() + serializer_class = api_serializers.UserSerializer + + def get_object(self): + if self.kwargs.get('pk') == 'self': + self.kwargs['pk'] = self.request.user.id + return super().get_object() \ No newline at end of file -- GitLab From 1854219d7f99dc7489d895db424284d0a7747416 Mon Sep 17 00:00:00 2001 From: Bunga Amalia Kurniawati Date: Tue, 25 May 2021 11:45:59 +0700 Subject: [PATCH 6/7] [REFACTOR] memperbaiki format file views --- api/views/auth.py | 7 ++++--- api/views/bank.py | 2 +- api/views/batch.py | 3 +++ api/views/cart.py | 23 +++++++++++--------- api/views/choices.py | 4 +++- api/views/config.py | 1 + api/views/donation.py | 2 +- api/views/product.py | 45 +++++++++++++++++++++------------------- api/views/program.py | 21 ++++++++++++++----- api/views/report.py | 27 +++++++++++++++--------- api/views/transaction.py | 6 ++++-- api/views/user.py | 4 +++- 12 files changed, 90 insertions(+), 55 deletions(-) diff --git a/api/views/auth.py b/api/views/auth.py index 271d323..452e3f8 100644 --- a/api/views/auth.py +++ b/api/views/auth.py @@ -20,6 +20,7 @@ from api import ( ) from home_industry import utils as home_industry_utils + class AuthRegister(generics.CreateAPIView): permission_classes = [api_permissions.IsAnonymousUser] serializer_class = api_serializers.UserSerializer @@ -32,7 +33,7 @@ class AuthCredLogin(knox_views.LoginView): def get_serializer(self, *args, **kwargs): return self.serializer_class(*args, **kwargs) - def post(self, request, format=None): # pylint: disable=redefined-builtin + def post(self, request, format=None): # pylint: disable=redefined-builtin serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) user = serializer.validated_data['user'] @@ -68,7 +69,7 @@ class AuthOTPLogin(knox_views.LoginView): def get_serializer(self, *args, **kwargs): return self.serializer_class(*args, **kwargs) - def post(self, request, format=None): # pylint: disable=redefined-builtin + def post(self, request, format=None): # pylint: disable=redefined-builtin http_authorization = self.request.META.get('HTTP_AUTHORIZATION') username = api_utils.get_username_from_bearer_token(http_authorization) serializer = self.get_serializer(data=request.data) @@ -92,4 +93,4 @@ class AuthResendOTP(rest_framework_views.APIView): user.otp = api_utils.generate_otp() user.save() api_utils.send_otp(str(user.phone_number), user.otp) - return response.Response(status=status.HTTP_204_NO_CONTENT) \ No newline at end of file + return response.Response(status=status.HTTP_204_NO_CONTENT) diff --git a/api/views/bank.py b/api/views/bank.py index 1fc205a..d61eeb9 100644 --- a/api/views/bank.py +++ b/api/views/bank.py @@ -20,6 +20,7 @@ from api import ( ) from home_industry import utils as home_industry_utils + class BankAccountTransferDestinationList(generics.ListCreateAPIView): filter_backends = [rest_framework_filters.SearchFilter] pagination_class = paginations.SmallResultsSetPagination @@ -39,4 +40,3 @@ class BankAccountTransferDestinationDetail(generics.RetrieveUpdateDestroyAPIView ] queryset = models.BankAccountTransferDestination.objects.all() serializer_class = api_serializers.BankAccountTransferDestinationSerializer - diff --git a/api/views/batch.py b/api/views/batch.py index c6d4c36..9a91e27 100644 --- a/api/views/batch.py +++ b/api/views/batch.py @@ -20,6 +20,7 @@ from api import ( ) from home_industry import utils as home_industry_utils + class BatchList(generics.ListCreateAPIView): filter_backends = [ rest_framework.DjangoFilterBackend, @@ -61,6 +62,7 @@ class BatchList(generics.ListCreateAPIView): return queryset.filter(user=self.request.user) return queryset + class BatchDetail(generics.RetrieveUpdateDestroyAPIView): permission_classes = [ api_permissions.IsAdminUserOrReadOnly, @@ -69,6 +71,7 @@ class BatchDetail(generics.RetrieveUpdateDestroyAPIView): queryset = models.Batch.objects.all() serializer_class = api_serializers.BatchSerializer + class BatchCreate(rest_framework_views.APIView): permission_classes = [rest_framework_permissions.IsAuthenticated] serializer_class = api_serializers.BatchCreateSerializer diff --git a/api/views/cart.py b/api/views/cart.py index 2198acf..afc2014 100644 --- a/api/views/cart.py +++ b/api/views/cart.py @@ -20,6 +20,7 @@ from api import ( ) from home_industry import utils as home_industry_utils + class CartUpdate(rest_framework_views.APIView): permission_classes = [rest_framework_permissions.IsAuthenticated] serializer_class = api_serializers.CartUpdateSerializer @@ -65,7 +66,8 @@ class CartOverview(rest_framework_views.APIView): status=status.HTTP_200_OK ) return response.Response( - {'item_subtotal': str(item_subtotal), 'shipping_costs': str(shipping_costs)}, + {'item_subtotal': str(item_subtotal), + 'shipping_costs': str(shipping_costs)}, status=status.HTTP_200_OK ) @@ -83,7 +85,7 @@ class CartCheckout(rest_framework_views.APIView): user = request.user shipment_config = home_industry_utils.get_shipment_config() if user.sub_district.lower() != shipment_config.sub_district.lower(): - raise rest_framework_exceptions.ParseError(_( # pylint: disable=no-member + raise rest_framework_exceptions.ParseError(_( # pylint: disable=no-member 'Cannot process shipment to other sub-districts other than {sub_district}.' ).format(sub_district=shipment_config.sub_district)) shopping_cart = models.ShoppingCart.objects.get(user=user) @@ -96,18 +98,18 @@ class CartCheckout(rest_framework_views.APIView): transaction_status = ( '001' if serializer.validated_data['payment_method'] == 'TRF' else '002' ) - + transaction = models.Transaction.objects.create( user=user, payment_method=serializer.validated_data['payment_method'], donation=serializer.validated_data['donation'], transaction_status=transaction_status, - batch = ( - None if serializer.validated_data['payment_method'] == 'TRF' - else models.Batch.objects.filter( - start_date__lte=timezone.now().date(), - end_date__gte=timezone.now().date()).first() - ) + batch=( + None if serializer.validated_data['payment_method'] == 'TRF' + else models.Batch.objects.filter( + start_date__lte=timezone.now().date(), + end_date__gte=timezone.now().date()).first() + ) ) is_success = True @@ -245,5 +247,6 @@ class ShoppingCartDetail(generics.RetrieveAPIView): def get_object(self): if self.kwargs.get('pk') == 'self': - self.kwargs['pk'] = models.ShoppingCart.objects.get(user=self.request.user).id + self.kwargs['pk'] = models.ShoppingCart.objects.get( + user=self.request.user).id return super().get_object() diff --git a/api/views/choices.py b/api/views/choices.py index d18e300..d4016bc 100644 --- a/api/views/choices.py +++ b/api/views/choices.py @@ -20,13 +20,15 @@ from api import ( ) from home_industry import utils as home_industry_utils + class ChoicesAPIView(rest_framework_views.APIView): choices = None permission_classes = [rest_framework_permissions.IsAuthenticated] def get(self, request, _format=None): assert self.choices is not None, ( - '{} should include a `choices` attribute.'.format(self.__class__.__name__) + '{} should include a `choices` attribute.'.format( + self.__class__.__name__) ) return response.Response(api_utils.map_choices(self.choices), status=status.HTTP_200_OK) diff --git a/api/views/config.py b/api/views/config.py index 312807a..724ff8b 100644 --- a/api/views/config.py +++ b/api/views/config.py @@ -20,6 +20,7 @@ from api import ( ) from home_industry import utils as home_industry_utils + class AppConfigDetail(generics.RetrieveUpdateAPIView): permission_classes = [rest_framework_permissions.IsAdminUser] queryset = models.AppConfig.objects.all() diff --git a/api/views/donation.py b/api/views/donation.py index f395df1..4435349 100644 --- a/api/views/donation.py +++ b/api/views/donation.py @@ -20,6 +20,7 @@ from api import ( ) from home_industry import utils as home_industry_utils + class DonationCreate(rest_framework_views.APIView): permission_classes = [rest_framework_permissions.IsAuthenticated] serializer_class = api_serializers.DonationCreateSerializer @@ -84,7 +85,6 @@ class DonationCreate(rest_framework_views.APIView): ) - class DonationReuploadProofOfBankTransfer(rest_framework_views.APIView): permission_classes = [rest_framework_permissions.IsAuthenticated] serializer_class = api_serializers.DonationReuploadProofOfBankTransferSerializer diff --git a/api/views/product.py b/api/views/product.py index 3a309ca..a51aae5 100644 --- a/api/views/product.py +++ b/api/views/product.py @@ -20,6 +20,7 @@ from api import ( ) from home_industry import utils as home_industry_utils + class CategoryList(generics.ListCreateAPIView): filter_backends = [ rest_framework.DjangoFilterBackend, @@ -125,12 +126,13 @@ class ProductList(generics.ListCreateAPIView): price=serializer.validated_data['price'], stock=serializer.validated_data['stock'], modal=serializer.validated_data['modal'], - subcategory=models.Subcategory.objects.get(name=serializer.validated_data['subcategory']), + subcategory=models.Subcategory.objects.get( + name=serializer.validated_data['subcategory']), total_profit=0, unit=serializer.validated_data['unit'], image=validated_image ) - product.profit= (product.price - product.modal) + product.profit = (product.price - product.modal) product.save() return response.Response( {'id': product.id}, @@ -138,7 +140,6 @@ class ProductList(generics.ListCreateAPIView): ) - class ProductDetail(generics.RetrieveUpdateDestroyAPIView): permission_classes = [ api_permissions.IsAdminUserOrReadOnly, @@ -151,44 +152,46 @@ class ProductDetail(generics.RetrieveUpdateDestroyAPIView): # leave this intact serializer_class = self.get_serializer_class() kwargs["context"] = self.get_serializer_context() - - if (self.request != None): if (self.request.data.get("price") != None) and (self.request.data.get("modal") != None): draft_request_data = self.request.data.copy() - profit= int(self.request.data['price'])-int(self.request.data['modal']) - new_profit={'profit': profit} + profit = int(self.request.data['price']) - \ + int(self.request.data['modal']) + new_profit = {'profit': profit} draft_request_data.update(new_profit) kwargs["data"] = draft_request_data return serializer_class(*args, **kwargs) else: if (self.request.data.get("price") != None): - - instance=self.get_object() + + instance = self.get_object() draft_request_data = self.request.data.copy() - profit= int(self.request.data['price'])-int(instance.modal) - new_profit={'profit': profit} + profit = int( + self.request.data['price'])-int(instance.modal) + new_profit = {'profit': profit} draft_request_data.update(new_profit) - + kwargs["data"] = draft_request_data return serializer_class(*args, **kwargs) elif (self.request.data.get("modal") != None): - instance=self.get_object() + instance = self.get_object() draft_request_data = self.request.data.copy() - profit= int(instance.price)-int(self.request.data['modal']) - new_profit={'profit': profit} + profit = int(instance.price) - \ + int(self.request.data['modal']) + new_profit = {'profit': profit} draft_request_data.update(new_profit) - + kwargs["data"] = draft_request_data return serializer_class(*args, **kwargs) - + return serializer_class(*args, **kwargs) def partial_update(self, request, *args, **kwargs): instance = self.get_object() - - serializer = self.get_serializer(instance,data=request.data, partial=True) + + serializer = self.get_serializer( + instance, data=request.data, partial=True) serializer.is_valid(raise_exception=True) - - return super().partial_update(request, *args, **kwargs) # pylint: disable=no-member + + return super().partial_update(request, *args, **kwargs) # pylint: disable=no-member diff --git a/api/views/program.py b/api/views/program.py index db16210..579b5aa 100644 --- a/api/views/program.py +++ b/api/views/program.py @@ -20,6 +20,7 @@ from api import ( ) from home_industry import utils as home_industry_utils + class ProgramProgressList(generics.ListCreateAPIView): permission_classes = [ api_permissions.IsAdminUserOrReadOnly, @@ -35,13 +36,15 @@ class ProgramProgressList(generics.ListCreateAPIView): serializer.save(program=self.get_program()) def get_program(self): - program = models.Program.objects.filter(id=self.kwargs.get(self.lookup_field)).first() + program = models.Program.objects.filter( + id=self.kwargs.get(self.lookup_field)).first() if program is None: raise rest_framework_exceptions.NotFound(_( 'Program not found.' )) return program + class ProgramList(generics.ListCreateAPIView): filter_backends = [ rest_framework.DjangoFilterBackend, @@ -68,6 +71,7 @@ class ProgramDetail(generics.RetrieveUpdateDestroyAPIView): queryset = models.Program.objects.all() serializer_class = api_serializers.ProgramSerializer + class ProgramDonationList(generics.ListAPIView): filter_backends = [ rest_framework.DjangoFilterBackend, @@ -80,7 +84,8 @@ class ProgramDonationList(generics.ListAPIView): permission_classes = [rest_framework_permissions.IsAuthenticated] queryset = models.ProgramDonation.objects.all() schema = schemas.ProgramDonationListSchema() - search_fields = ['donation_number', 'user_full_name', 'program_name', 'donation_type'] + search_fields = ['donation_number', 'user_full_name', + 'program_name', 'donation_type'] serializer_class = api_serializers.ProgramDonationSerializer def filter_queryset(self, queryset): @@ -89,6 +94,7 @@ class ProgramDonationList(generics.ListAPIView): return queryset.filter(user=self.request.user) return queryset + @api_view(['DELETE']) @csrf_exempt def delete_donation_by_program(request, pid): @@ -98,6 +104,7 @@ def delete_donation_by_program(request, pid): donation.delete() return response.Response(status=status.HTTP_204_NO_CONTENT) + class ProgramDonationListCSH(generics.ListAPIView): filter_backends = [ rest_framework.DjangoFilterBackend, @@ -110,7 +117,8 @@ class ProgramDonationListCSH(generics.ListAPIView): permission_classes = [rest_framework_permissions.IsAuthenticated] queryset = models.ProgramDonation.objects.filter(donation_type='CSH') schema = schemas.ProgramDonationListSchema() - search_fields = ['donation_number', 'user_full_name', 'program_name', 'donation_type'] + search_fields = ['donation_number', 'user_full_name', + 'program_name', 'donation_type'] serializer_class = api_serializers.ProgramDonationSerializer def filter_queryset(self, queryset): @@ -119,6 +127,7 @@ class ProgramDonationListCSH(generics.ListAPIView): return queryset.filter(user=self.request.user) return queryset + class ProgramDonationListGDS(generics.ListAPIView): filter_backends = [ rest_framework.DjangoFilterBackend, @@ -131,7 +140,8 @@ class ProgramDonationListGDS(generics.ListAPIView): permission_classes = [rest_framework_permissions.IsAuthenticated] queryset = models.ProgramDonation.objects.filter(donation_type='GDS') schema = schemas.ProgramDonationListSchema() - search_fields = ['donation_number', 'user_full_name', 'program_name', 'donation_type'] + search_fields = ['donation_number', 'user_full_name', + 'program_name', 'donation_type'] serializer_class = api_serializers.ProgramDonationSerializer def filter_queryset(self, queryset): @@ -140,6 +150,7 @@ class ProgramDonationListGDS(generics.ListAPIView): return queryset.filter(user=self.request.user) return queryset + class ProgramDonationDetail(generics.RetrieveUpdateAPIView): permission_classes = [ api_permissions.IsAdminUserOrOwnerReadOnly, @@ -156,4 +167,4 @@ class ProgramDonationDetail(generics.RetrieveUpdateAPIView): raise rest_framework_exceptions.PermissionDenied(_( 'Cannot update program donation because it has a completed or canceled status.' )) - return super().update(request, *args, **kwargs) # pylint: disable=no-member + return super().update(request, *args, **kwargs) # pylint: disable=no-member diff --git a/api/views/report.py b/api/views/report.py index 7d3e52e..5b29ae5 100644 --- a/api/views/report.py +++ b/api/views/report.py @@ -20,6 +20,7 @@ from api import ( ) from home_industry import utils as home_industry_utils + class ReportAPIView(rest_framework_views.APIView): permission_classes = [rest_framework_permissions.IsAdminUser] report_function = None @@ -29,14 +30,16 @@ class ReportAPIView(rest_framework_views.APIView): raise NotImplementedError def get_serializer(self, *args, **kwargs): - return self.serializer_class(*args, **kwargs) # pylint: disable=not-callable + return self.serializer_class(*args, **kwargs) # pylint: disable=not-callable def get(self, request, _format=None): assert self.report_function is not None, ( - '{} should include a `report_function` attribute.'.format(self.__class__.__name__) + '{} should include a `report_function` attribute.'.format( + self.__class__.__name__) ) assert self.report_function is not None, ( - '{} should include a `serializer_class` attribute.'.format(self.__class__.__name__) + '{} should include a `serializer_class` attribute.'.format( + self.__class__.__name__) ) serializer = self.get_serializer(data=request.query_params) serializer.is_valid(raise_exception=True) @@ -51,11 +54,12 @@ class ReportTransaction(ReportAPIView): serializer_class = api_serializers.ReportTransactionSerializer def get_filename(self, query_params): - filename = '{}.xlsx'.format(_( # pylint: disable=no-member + filename = '{}.xlsx'.format(_( # pylint: disable=no-member 'Transaction Report from {date_from} to {date_to} for {batch_name}' ).format( date_from=query_params.get('created_at_date_range_after', '_'), - date_to=query_params.get('created_at_date_range_before', str(timezone.now())[:10]), + date_to=query_params.get( + 'created_at_date_range_before', str(timezone.now())[:10]), batch_name=query_params.get('batch_name', '_') )) return filename @@ -67,24 +71,27 @@ class ReportProgramDonationCSH(ReportAPIView): serializer_class = api_serializers.ReportProgramDonationSerializer def get_filename(self, query_params): - filename = '{}.xlsx'.format(_( # pylint: disable=no-member + filename = '{}.xlsx'.format(_( # pylint: disable=no-member 'Program Donation Report from {date_from} to {date_to}' ).format( date_from=query_params.get('created_at_date_range_after', '_'), - date_to=query_params.get('created_at_date_range_before', str(timezone.now())[:10]) + date_to=query_params.get( + 'created_at_date_range_before', str(timezone.now())[:10]) )) return filename + class ReportProgramDonationGDS(ReportAPIView): report_function = reports_writer.create_program_donation_report_gds schema = schemas.ReportProgramDonationSchema() serializer_class = api_serializers.ReportProgramDonationSerializer def get_filename(self, query_params): - filename = '{}.xlsx'.format(_( # pylint: disable=no-member + filename = '{}.xlsx'.format(_( # pylint: disable=no-member 'Program Donation Report from {date_from} to {date_to}' ).format( date_from=query_params.get('created_at_date_range_after', '_'), - date_to=query_params.get('created_at_date_range_before', str(timezone.now())[:10]) + date_to=query_params.get( + 'created_at_date_range_before', str(timezone.now())[:10]) )) - return filename \ No newline at end of file + return filename diff --git a/api/views/transaction.py b/api/views/transaction.py index 0833808..f362565 100644 --- a/api/views/transaction.py +++ b/api/views/transaction.py @@ -20,6 +20,7 @@ from api import ( ) from home_industry import utils as home_industry_utils + class TransactionList(generics.ListAPIView): filter_backends = [ rest_framework.DjangoFilterBackend, @@ -60,5 +61,6 @@ class TransactionDetail(generics.RetrieveUpdateAPIView): )) if serializer.validated_data['transaction_status'] == '006': transaction_items = instance.transaction_items.all() - api_utils.return_transaction_items_to_product_stock(transaction_items) - return super().update(request, *args, **kwargs) # pylint: disable=no-member + api_utils.return_transaction_items_to_product_stock( + transaction_items) + return super().update(request, *args, **kwargs) # pylint: disable=no-member diff --git a/api/views/user.py b/api/views/user.py index 4609737..372f276 100644 --- a/api/views/user.py +++ b/api/views/user.py @@ -20,6 +20,7 @@ from api import ( ) from home_industry import utils as home_industry_utils + class UserList(generics.ListCreateAPIView): filter_backends = [ rest_framework.DjangoFilterBackend, @@ -37,6 +38,7 @@ class UserList(generics.ListCreateAPIView): search_fields = ['username', 'full_name', 'phone_number'] serializer_class = api_serializers.UserSerializer + class UserDetail(generics.RetrieveUpdateDestroyAPIView): permission_classes = [ api_permissions.IsAdminUserOrSelf, @@ -48,4 +50,4 @@ class UserDetail(generics.RetrieveUpdateDestroyAPIView): def get_object(self): if self.kwargs.get('pk') == 'self': self.kwargs['pk'] = self.request.user.id - return super().get_object() \ No newline at end of file + return super().get_object() -- GitLab From a269edd4580d73b466d0a2d9a40bb8ad1fba2cd7 Mon Sep 17 00:00:00 2001 From: Bunga Amalia Kurniawati Date: Tue, 25 May 2021 12:06:51 +0700 Subject: [PATCH 7/7] [REFACTOR] menghapus import yang tidak dibutuhkan pada file views --- api/views/auth.py | 27 +++++++++------------------ api/views/bank.py | 27 ++++++--------------------- api/views/batch.py | 30 +++++++++++------------------- api/views/cart.py | 29 ++++++++++++----------------- api/views/choices.py | 26 +++++--------------------- api/views/config.py | 27 ++++++--------------------- api/views/donation.py | 27 +++++++-------------------- api/views/product.py | 26 ++++++++------------------ api/views/program.py | 29 +++++++++++------------------ api/views/report.py | 24 +++++------------------- api/views/transaction.py | 29 ++++++++++------------------- api/views/user.py | 26 ++++++-------------------- 12 files changed, 96 insertions(+), 231 deletions(-) diff --git a/api/views/auth.py b/api/views/auth.py index 452e3f8..764a741 100644 --- a/api/views/auth.py +++ b/api/views/auth.py @@ -1,24 +1,15 @@ -from django import http, shortcuts +from api import models +from api import permissions as api_permissions +from api import serializers as api_serializers +from api import utils as api_utils +from django import shortcuts from django.contrib import auth -from django.db import transaction as db_transaction, utils as db_utils -from django.db.models import deletion -from django.utils import timezone -from django.utils.translation import gettext_lazy as _ -from django_filters import rest_framework from knox import views as knox_views -from rest_framework import ( - exceptions as rest_framework_exceptions, filters as rest_framework_filters, generics, - permissions as rest_framework_permissions, response, status, views as rest_framework_views -) +from rest_framework import generics +from rest_framework import permissions as rest_framework_permissions +from rest_framework import response, status +from rest_framework import views as rest_framework_views from rest_framework.authtoken import serializers as authtoken_serializers -from rest_framework.decorators import api_view -from django.views.decorators.csrf import csrf_exempt -from api import ( - constants, exceptions as api_exceptions, filters as api_filters, models, paginations, - permissions as api_permissions, reports_writer, schemas, serializers as api_serializers, - utils as api_utils -) -from home_industry import utils as home_industry_utils class AuthRegister(generics.CreateAPIView): diff --git a/api/views/bank.py b/api/views/bank.py index d61eeb9..20ddfcf 100644 --- a/api/views/bank.py +++ b/api/views/bank.py @@ -1,24 +1,9 @@ -from django import http, shortcuts -from django.contrib import auth -from django.db import transaction as db_transaction, utils as db_utils -from django.db.models import deletion -from django.utils import timezone -from django.utils.translation import gettext_lazy as _ -from django_filters import rest_framework -from knox import views as knox_views -from rest_framework import ( - exceptions as rest_framework_exceptions, filters as rest_framework_filters, generics, - permissions as rest_framework_permissions, response, status, views as rest_framework_views -) -from rest_framework.authtoken import serializers as authtoken_serializers -from rest_framework.decorators import api_view -from django.views.decorators.csrf import csrf_exempt -from api import ( - constants, exceptions as api_exceptions, filters as api_filters, models, paginations, - permissions as api_permissions, reports_writer, schemas, serializers as api_serializers, - utils as api_utils -) -from home_industry import utils as home_industry_utils +from api import models, paginations +from api import permissions as api_permissions +from api import serializers as api_serializers +from rest_framework import filters as rest_framework_filters +from rest_framework import generics +from rest_framework import permissions as rest_framework_permissions class BankAccountTransferDestinationList(generics.ListCreateAPIView): diff --git a/api/views/batch.py b/api/views/batch.py index 9a91e27..f8de732 100644 --- a/api/views/batch.py +++ b/api/views/batch.py @@ -1,24 +1,16 @@ -from django import http, shortcuts -from django.contrib import auth -from django.db import transaction as db_transaction, utils as db_utils -from django.db.models import deletion -from django.utils import timezone +from api import filters as api_filters +from api import models, paginations +from api import permissions as api_permissions +from api import schemas +from api import serializers as api_serializers from django.utils.translation import gettext_lazy as _ from django_filters import rest_framework -from knox import views as knox_views -from rest_framework import ( - exceptions as rest_framework_exceptions, filters as rest_framework_filters, generics, - permissions as rest_framework_permissions, response, status, views as rest_framework_views -) -from rest_framework.authtoken import serializers as authtoken_serializers -from rest_framework.decorators import api_view -from django.views.decorators.csrf import csrf_exempt -from api import ( - constants, exceptions as api_exceptions, filters as api_filters, models, paginations, - permissions as api_permissions, reports_writer, schemas, serializers as api_serializers, - utils as api_utils -) -from home_industry import utils as home_industry_utils +from rest_framework import exceptions as rest_framework_exceptions +from rest_framework import filters as rest_framework_filters +from rest_framework import generics +from rest_framework import permissions as rest_framework_permissions +from rest_framework import response, status +from rest_framework import views as rest_framework_views class BatchList(generics.ListCreateAPIView): diff --git a/api/views/cart.py b/api/views/cart.py index afc2014..ddd7545 100644 --- a/api/views/cart.py +++ b/api/views/cart.py @@ -1,24 +1,19 @@ -from django import http, shortcuts -from django.contrib import auth -from django.db import transaction as db_transaction, utils as db_utils -from django.db.models import deletion +from api import models, paginations +from api import permissions as api_permissions +from api import serializers as api_serializers +from api import utils as api_utils +from django import shortcuts +from django.db import transaction as db_transaction +from django.db import utils as db_utils from django.utils import timezone from django.utils.translation import gettext_lazy as _ from django_filters import rest_framework -from knox import views as knox_views -from rest_framework import ( - exceptions as rest_framework_exceptions, filters as rest_framework_filters, generics, - permissions as rest_framework_permissions, response, status, views as rest_framework_views -) -from rest_framework.authtoken import serializers as authtoken_serializers -from rest_framework.decorators import api_view -from django.views.decorators.csrf import csrf_exempt -from api import ( - constants, exceptions as api_exceptions, filters as api_filters, models, paginations, - permissions as api_permissions, reports_writer, schemas, serializers as api_serializers, - utils as api_utils -) from home_industry import utils as home_industry_utils +from rest_framework import exceptions as rest_framework_exceptions +from rest_framework import generics +from rest_framework import permissions as rest_framework_permissions +from rest_framework import response, status +from rest_framework import views as rest_framework_views class CartUpdate(rest_framework_views.APIView): diff --git a/api/views/choices.py b/api/views/choices.py index d4016bc..53dbc86 100644 --- a/api/views/choices.py +++ b/api/views/choices.py @@ -1,24 +1,8 @@ -from django import http, shortcuts -from django.contrib import auth -from django.db import transaction as db_transaction, utils as db_utils -from django.db.models import deletion -from django.utils import timezone -from django.utils.translation import gettext_lazy as _ -from django_filters import rest_framework -from knox import views as knox_views -from rest_framework import ( - exceptions as rest_framework_exceptions, filters as rest_framework_filters, generics, - permissions as rest_framework_permissions, response, status, views as rest_framework_views -) -from rest_framework.authtoken import serializers as authtoken_serializers -from rest_framework.decorators import api_view -from django.views.decorators.csrf import csrf_exempt -from api import ( - constants, exceptions as api_exceptions, filters as api_filters, models, paginations, - permissions as api_permissions, reports_writer, schemas, serializers as api_serializers, - utils as api_utils -) -from home_industry import utils as home_industry_utils +from api import constants +from api import utils as api_utils +from rest_framework import permissions as rest_framework_permissions +from rest_framework import response, status +from rest_framework import views as rest_framework_views class ChoicesAPIView(rest_framework_views.APIView): diff --git a/api/views/config.py b/api/views/config.py index 724ff8b..4bc731b 100644 --- a/api/views/config.py +++ b/api/views/config.py @@ -1,24 +1,9 @@ -from django import http, shortcuts -from django.contrib import auth -from django.db import transaction as db_transaction, utils as db_utils -from django.db.models import deletion -from django.utils import timezone -from django.utils.translation import gettext_lazy as _ -from django_filters import rest_framework -from knox import views as knox_views -from rest_framework import ( - exceptions as rest_framework_exceptions, filters as rest_framework_filters, generics, - permissions as rest_framework_permissions, response, status, views as rest_framework_views -) -from rest_framework.authtoken import serializers as authtoken_serializers -from rest_framework.decorators import api_view -from django.views.decorators.csrf import csrf_exempt -from api import ( - constants, exceptions as api_exceptions, filters as api_filters, models, paginations, - permissions as api_permissions, reports_writer, schemas, serializers as api_serializers, - utils as api_utils -) -from home_industry import utils as home_industry_utils +from api import models +from api import permissions as api_permissions +from api import serializers as api_serializers +from django import shortcuts +from rest_framework import generics +from rest_framework import permissions as rest_framework_permissions class AppConfigDetail(generics.RetrieveUpdateAPIView): diff --git a/api/views/donation.py b/api/views/donation.py index 4435349..ce8f899 100644 --- a/api/views/donation.py +++ b/api/views/donation.py @@ -1,24 +1,11 @@ -from django import http, shortcuts -from django.contrib import auth -from django.db import transaction as db_transaction, utils as db_utils -from django.db.models import deletion -from django.utils import timezone +from api import models +from api import serializers as api_serializers +from django import shortcuts from django.utils.translation import gettext_lazy as _ -from django_filters import rest_framework -from knox import views as knox_views -from rest_framework import ( - exceptions as rest_framework_exceptions, filters as rest_framework_filters, generics, - permissions as rest_framework_permissions, response, status, views as rest_framework_views -) -from rest_framework.authtoken import serializers as authtoken_serializers -from rest_framework.decorators import api_view -from django.views.decorators.csrf import csrf_exempt -from api import ( - constants, exceptions as api_exceptions, filters as api_filters, models, paginations, - permissions as api_permissions, reports_writer, schemas, serializers as api_serializers, - utils as api_utils -) -from home_industry import utils as home_industry_utils +from rest_framework import exceptions as rest_framework_exceptions +from rest_framework import permissions as rest_framework_permissions +from rest_framework import response, status +from rest_framework import views as rest_framework_views class DonationCreate(rest_framework_views.APIView): diff --git a/api/views/product.py b/api/views/product.py index a51aae5..bd3a357 100644 --- a/api/views/product.py +++ b/api/views/product.py @@ -1,24 +1,14 @@ -from django import http, shortcuts -from django.contrib import auth -from django.db import transaction as db_transaction, utils as db_utils +from api import exceptions as api_exceptions +from api import models, paginations +from api import permissions as api_permissions +from api import serializers as api_serializers from django.db.models import deletion -from django.utils import timezone from django.utils.translation import gettext_lazy as _ from django_filters import rest_framework -from knox import views as knox_views -from rest_framework import ( - exceptions as rest_framework_exceptions, filters as rest_framework_filters, generics, - permissions as rest_framework_permissions, response, status, views as rest_framework_views -) -from rest_framework.authtoken import serializers as authtoken_serializers -from rest_framework.decorators import api_view -from django.views.decorators.csrf import csrf_exempt -from api import ( - constants, exceptions as api_exceptions, filters as api_filters, models, paginations, - permissions as api_permissions, reports_writer, schemas, serializers as api_serializers, - utils as api_utils -) -from home_industry import utils as home_industry_utils +from rest_framework import filters as rest_framework_filters +from rest_framework import generics +from rest_framework import permissions as rest_framework_permissions +from rest_framework import response, status class CategoryList(generics.ListCreateAPIView): diff --git a/api/views/program.py b/api/views/program.py index 579b5aa..e9682f8 100644 --- a/api/views/program.py +++ b/api/views/program.py @@ -1,24 +1,17 @@ -from django import http, shortcuts -from django.contrib import auth -from django.db import transaction as db_transaction, utils as db_utils -from django.db.models import deletion -from django.utils import timezone +from api import filters as api_filters +from api import models, paginations +from api import permissions as api_permissions +from api import schemas +from api import serializers as api_serializers from django.utils.translation import gettext_lazy as _ +from django.views.decorators.csrf import csrf_exempt from django_filters import rest_framework -from knox import views as knox_views -from rest_framework import ( - exceptions as rest_framework_exceptions, filters as rest_framework_filters, generics, - permissions as rest_framework_permissions, response, status, views as rest_framework_views -) -from rest_framework.authtoken import serializers as authtoken_serializers +from rest_framework import exceptions as rest_framework_exceptions +from rest_framework import filters as rest_framework_filters +from rest_framework import generics +from rest_framework import permissions as rest_framework_permissions +from rest_framework import response, status from rest_framework.decorators import api_view -from django.views.decorators.csrf import csrf_exempt -from api import ( - constants, exceptions as api_exceptions, filters as api_filters, models, paginations, - permissions as api_permissions, reports_writer, schemas, serializers as api_serializers, - utils as api_utils -) -from home_industry import utils as home_industry_utils class ProgramProgressList(generics.ListCreateAPIView): diff --git a/api/views/report.py b/api/views/report.py index 5b29ae5..fdf2115 100644 --- a/api/views/report.py +++ b/api/views/report.py @@ -1,24 +1,10 @@ -from django import http, shortcuts -from django.contrib import auth -from django.db import transaction as db_transaction, utils as db_utils -from django.db.models import deletion +from api import reports_writer, schemas +from api import serializers as api_serializers +from django import http from django.utils import timezone from django.utils.translation import gettext_lazy as _ -from django_filters import rest_framework -from knox import views as knox_views -from rest_framework import ( - exceptions as rest_framework_exceptions, filters as rest_framework_filters, generics, - permissions as rest_framework_permissions, response, status, views as rest_framework_views -) -from rest_framework.authtoken import serializers as authtoken_serializers -from rest_framework.decorators import api_view -from django.views.decorators.csrf import csrf_exempt -from api import ( - constants, exceptions as api_exceptions, filters as api_filters, models, paginations, - permissions as api_permissions, reports_writer, schemas, serializers as api_serializers, - utils as api_utils -) -from home_industry import utils as home_industry_utils +from rest_framework import permissions as rest_framework_permissions +from rest_framework import views as rest_framework_views class ReportAPIView(rest_framework_views.APIView): diff --git a/api/views/transaction.py b/api/views/transaction.py index f362565..b057b88 100644 --- a/api/views/transaction.py +++ b/api/views/transaction.py @@ -1,24 +1,15 @@ -from django import http, shortcuts -from django.contrib import auth -from django.db import transaction as db_transaction, utils as db_utils -from django.db.models import deletion -from django.utils import timezone +from api import filters as api_filters +from api import models, paginations +from api import permissions as api_permissions +from api import schemas +from api import serializers as api_serializers +from api import utils as api_utils from django.utils.translation import gettext_lazy as _ from django_filters import rest_framework -from knox import views as knox_views -from rest_framework import ( - exceptions as rest_framework_exceptions, filters as rest_framework_filters, generics, - permissions as rest_framework_permissions, response, status, views as rest_framework_views -) -from rest_framework.authtoken import serializers as authtoken_serializers -from rest_framework.decorators import api_view -from django.views.decorators.csrf import csrf_exempt -from api import ( - constants, exceptions as api_exceptions, filters as api_filters, models, paginations, - permissions as api_permissions, reports_writer, schemas, serializers as api_serializers, - utils as api_utils -) -from home_industry import utils as home_industry_utils +from rest_framework import exceptions as rest_framework_exceptions +from rest_framework import filters as rest_framework_filters +from rest_framework import generics +from rest_framework import permissions as rest_framework_permissions class TransactionList(generics.ListAPIView): diff --git a/api/views/user.py b/api/views/user.py index 372f276..e27b217 100644 --- a/api/views/user.py +++ b/api/views/user.py @@ -1,24 +1,10 @@ -from django import http, shortcuts -from django.contrib import auth -from django.db import transaction as db_transaction, utils as db_utils -from django.db.models import deletion -from django.utils import timezone -from django.utils.translation import gettext_lazy as _ +from api import models, paginations +from api import permissions as api_permissions +from api import serializers as api_serializers from django_filters import rest_framework -from knox import views as knox_views -from rest_framework import ( - exceptions as rest_framework_exceptions, filters as rest_framework_filters, generics, - permissions as rest_framework_permissions, response, status, views as rest_framework_views -) -from rest_framework.authtoken import serializers as authtoken_serializers -from rest_framework.decorators import api_view -from django.views.decorators.csrf import csrf_exempt -from api import ( - constants, exceptions as api_exceptions, filters as api_filters, models, paginations, - permissions as api_permissions, reports_writer, schemas, serializers as api_serializers, - utils as api_utils -) -from home_industry import utils as home_industry_utils +from rest_framework import filters as rest_framework_filters +from rest_framework import generics +from rest_framework import permissions as rest_framework_permissions class UserList(generics.ListCreateAPIView): -- GitLab