Fakultas Ilmu Komputer UI

Commit e912fe2a authored by Ilma Ainur Rohma's avatar Ilma Ainur Rohma
Browse files

[REFACTOR] solve merge conflict

parents 81152e2c 330690cc
Pipeline #81449 passed with stages
in 2 minutes and 25 seconds
......@@ -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
# Generated by Django 3.0.7 on 2021-06-05 15:41
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('api', '0007_auto_20210603_2001'),
]
operations = [
migrations.AddField(
model_name='bankaccounttransferdestination',
name='bank_code_number',
field=models.CharField(default='000', max_length=100, verbose_name='bank code number'),
),
migrations.AddField(
model_name='programdonation',
name='transfer_destination_bank_code_number',
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='transfer destination bank code number'),
),
migrations.AddField(
model_name='transaction',
name='transfer_destination_bank_code_number',
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='transfer destination bank code number'),
),
]
......@@ -53,6 +53,7 @@ class User(auth_models.AbstractUser):
class BankAccountTransferDestination(db_models.Model):
id = db_models.UUIDField(default=uuid.uuid4, primary_key=True, verbose_name=_('ID'))
bank_name = db_models.CharField(max_length=100, verbose_name=_('bank name'))
bank_code_number = db_models.CharField(max_length=100, verbose_name=_('bank code number'), default='000')
bank_account_number = db_models.CharField(max_length=100, verbose_name=_('bank account number'))
bank_account_name = db_models.CharField(max_length=200, verbose_name=_('bank account name'))
......@@ -63,7 +64,7 @@ class BankAccountTransferDestination(db_models.Model):
verbose_name_plural = _('bank account transfer destinations')
def __str__(self):
return '{} - {}'.format(self.bank_name, self.bank_account_number)
return '{}: {} - {}'.format(self.bank_name, self.bank_code_number, self.bank_account_number)
class Category(db_models.Model):
......@@ -324,6 +325,12 @@ class Transaction(db_models.Model):
null=True,
verbose_name=_('transfer destination bank account number')
)
transfer_destination_bank_code_number = db_models.CharField(
blank=True,
max_length=100,
null=True,
verbose_name=_('transfer destination bank code number')
)
created_at = db_models.DateTimeField(
auto_now_add=True,
db_index=True,
......@@ -532,6 +539,12 @@ class ProgramDonation(db_models.Model):
max_length=100,
verbose_name=_('transfer destination bank account number')
)
transfer_destination_bank_code_number = db_models.CharField(
blank=True,
null=True,
max_length=100,
verbose_name=_('transfer destination bank code number')
)
goods_quantity = db_models.DecimalField(
blank=True,
null=True,
......
......@@ -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,
......
......@@ -18,7 +18,8 @@ USER_DATA = {
BANK_ACCOUNT_TRANSFER_DESTINATION = {
'bank_name': 'Dummy Bank Name',
'bank_account_number': 'Dummy Bank Account Number',
'bank_code_number': '011',
'bank_account_number': '123456789',
'bank_account_name': 'Dummy Bank Account Name',
}
......
......@@ -223,7 +223,7 @@ class UserSerializer(serializers.ModelSerializer):
class BankAccountTransferDestinationSerializer(serializers.ModelSerializer):
class Meta:
fields = ['id', 'bank_name', 'bank_account_number', 'bank_account_name']
fields = ['id', 'bank_name', 'bank_code_number', 'bank_account_number','bank_account_name']
model = models.BankAccountTransferDestination
read_only_fields = ['id']
......@@ -358,6 +358,7 @@ class TransactionSerializer(serializers.ModelSerializer):
'bank_account_transfer_destination',
'transfer_destination_bank_name',
'transfer_destination_bank_account_name',
'transfer_destination_bank_code_number',
'transfer_destination_bank_account_number',
'created_at',
'updated_at',
......@@ -389,6 +390,7 @@ class TransactionSerializer(serializers.ModelSerializer):
'bank_account_transfer_destination',
'transfer_destination_bank_name',
'transfer_destination_bank_account_name',
'transfer_destination_bank_code_number',
'transfer_destination_bank_account_number',
'created_at',
'updated_at',
......@@ -487,7 +489,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)
......@@ -522,6 +523,7 @@ class ProgramDonationSerializer(serializers.ModelSerializer):
'bank_account_transfer_destination',
'transfer_destination_bank_name',
'transfer_destination_bank_account_name',
'transfer_destination_bank_code_number',
'transfer_destination_bank_account_number',
'goods_quantity',
'goods_description',
......@@ -547,6 +549,7 @@ class ProgramDonationSerializer(serializers.ModelSerializer):
'bank_account_transfer_destination',
'transfer_destination_bank_name',
'transfer_destination_bank_account_name',
'transfer_destination_bank_code_number',
'transfer_destination_bank_account_number',
'created_at',
'updated_at',
......
......@@ -856,8 +856,9 @@ class BankAccountTransferDestinationTest(rest_framework_test.APITestCase):
)
self.assertEqual(
str(bank_account_transfer_destination),
'{} - {}'.format(
'{}: {} - {}'.format(
bank_account_transfer_destination.bank_name,
bank_account_transfer_destination.bank_code_number,
bank_account_transfer_destination.bank_account_number
)
)
......@@ -892,6 +893,12 @@ class BankAccountTransferDestinationTest(rest_framework_test.APITestCase):
)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(models.BankAccountTransferDestination.objects.count(), 1)
self.assertEqual(
models.BankAccountTransferDestination.objects.get(
id=response.data['id']
).bank_code_number,
data['bank_code_number']
)
self.assertEqual(
models.BankAccountTransferDestination.objects.get(
id=response.data['id']
......@@ -913,6 +920,7 @@ class BankAccountTransferDestinationTest(rest_framework_test.APITestCase):
**seeds.BANK_ACCOUNT_TRANSFER_DESTINATION
)
data = {
'bank_code_number': '333',
'bank_account_number': 'Another Dummy Bank Account Number',
}
response = request(
......@@ -923,6 +931,12 @@ class BankAccountTransferDestinationTest(rest_framework_test.APITestCase):
url_args=[bank_account_transfer_destination.id]
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(
models.BankAccountTransferDestination.objects.get(
id=bank_account_transfer_destination.id
).bank_code_number,
data['bank_code_number']
)
self.assertEqual(
models.BankAccountTransferDestination.objects.get(
id=bank_account_transfer_destination.id
......@@ -938,6 +952,12 @@ class BankAccountTransferDestinationTest(rest_framework_test.APITestCase):
url_args=[bank_account_transfer_destination.id]
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(
models.BankAccountTransferDestination.objects.get(
id=bank_account_transfer_destination.id
).bank_code_number,
data['bank_code_number']
)
self.assertEqual(
models.BankAccountTransferDestination.objects.get(
id=bank_account_transfer_destination.id
......@@ -950,6 +970,7 @@ class BankAccountTransferDestinationTest(rest_framework_test.APITestCase):
**seeds.BANK_ACCOUNT_TRANSFER_DESTINATION
)
data = {
'bank_code_number': '',
'bank_account_number': '',
}
response = request(
......
This diff is collapsed.
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
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 knox import views as knox_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
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)
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):
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
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 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):
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
)
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 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):
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'):