Skip to content

Commit

Permalink
Merge pull request #184 from FJNR-inc/develop
Browse files Browse the repository at this point in the history
New release
  • Loading branch information
RignonNoel authored Sep 14, 2019
2 parents b62682a + 1cad38e commit e9abea1
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 51 deletions.
2 changes: 1 addition & 1 deletion requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ pycodestyle==2.5.0
coveralls==1.8.2
responses==0.10.6
six==1.12.0
awscli==1.16.237
awscli==1.16.238
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ djangorestframework==3.10.3
django-cors-headers==3.1.0
django-filter==2.2.0
coreapi==2.3.3
factory-boy==2.11.1
factory-boy==2.12.0
Markdown==2.6.11
Pygments==2.3.1
Pygments==2.4.2
django-anymail==6.1.0
Pillow==6.1.0
django-simple-history==2.7.3
Expand Down
18 changes: 18 additions & 0 deletions store/tests/tests_viewset_Order.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,17 @@ def setUp(self):
reserved_seats=1,
has_shared_rooms=True,
)

self.option_retreat: OptionProduct = OptionProduct.objects.create(
name="Vegan",
details="Vegan details",
available=True,
price=50,
max_quantity=10
)
self.option_retreat.available_on_products.add(self.retreat)
self.option_retreat.save()

self.retreat_no_seats = Retreat.objects.create(
name="no_place_left_retreat",
seats=0,
Expand Down Expand Up @@ -2489,10 +2500,17 @@ def test_validate_coupon(self):
'content_type': 'timeslot',
'object_id': self.time_slot.id,
'quantity': 1,
'options': []
}, {
'content_type': 'retreat',
'object_id': self.retreat.id,
'quantity': 1,
'options': [
{
'id': self.option_retreat.id,
'quantity': 2
}
]
}],
'coupon': "ABCD1234",
}
Expand Down
118 changes: 70 additions & 48 deletions store/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.db import transaction
from django.http import Http404, HttpResponse, HttpRequest
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
Expand All @@ -20,7 +21,7 @@
from .exceptions import PaymentAPIError
from .models import (Package, Membership, Order, OrderLine, PaymentProfile,
CustomPayment, Coupon, CouponUser, Refund, BaseProduct,
OptionProduct)
OptionProduct, OrderLineBaseProduct)
from .permissions import IsOwner
from .resources import (MembershipResource, PackageResource, OrderResource,
OrderLineResource, CustomPaymentResource,
Expand Down Expand Up @@ -259,6 +260,7 @@ class OrderViewSet(ExportMixin, viewsets.ModelViewSet):

export_resource = OrderResource()

@transaction.atomic
@action(
methods=['post'], detail=False, permission_classes=[IsAuthenticated])
def validate_coupon(self, request, pk=None):
Expand All @@ -269,57 +271,77 @@ def validate_coupon(self, request, pk=None):
This is not the best way to do it and it could be improved.
"""
serializer = serializers.OrderSerializer(
data=request.data,
context={'request': request}
)
serializer.is_valid(raise_exception=True)
# Coupon is necessary for this view
if not serializer.validated_data.get('coupon'):
error = {
'coupon': [_("This field is required.")]
}
return Response(error, status=status.HTTP_400_BAD_REQUEST)
orderlines = serializer.validated_data.pop('order_lines', None)
coupon = serializer.validated_data.pop('coupon', None)
serializer.validated_data.pop('payment_token', None)
serializer.validated_data.pop('single_use_token', None)
order = Order(
**serializer.validated_data,
transaction_date=timezone.now(),
user=request.user,
)
order.save()

orderline_list = []
for idx, orderline in enumerate(orderlines):
orderline_list.append(
OrderLine(
**orderline,
order=order,
)
try:
sid = transaction.savepoint()
serializer = serializers.OrderSerializer(
data=request.data,
context={'request': request}
)
orderline_list[idx].save()

response = validate_coupon_for_order(coupon, order)
response['orderline'] = serializers.OrderLineSerializerNoOrder(
response['orderline'],
context={'request': request}
).data
response['orderline'].pop('url', None)
response['orderline'].pop('id', None)
response['orderline'].pop('order', None)
response['orderline'].pop('coupon', None)
response['orderline'].pop('coupon_real_value', None)
response['orderline'].pop('cost', None)
order.delete()
for orderline in orderline_list:
orderline.delete()
if response['valid_use']:
serializer.is_valid(raise_exception=True)
# Coupon is necessary for this view
if not serializer.validated_data.get('coupon'):
error = {
'coupon': [_("This field is required.")]
}
return Response(error, status=status.HTTP_400_BAD_REQUEST)
orderlines = serializer.validated_data.pop('order_lines', None)
coupon = serializer.validated_data.pop('coupon', None)
serializer.validated_data.pop('payment_token', None)
serializer.validated_data.pop('single_use_token', None)
order = Order(
**serializer.validated_data,
transaction_date=timezone.now(),
user=request.user,
)
order.save()

orderline_list = []
for idx, orderline in enumerate(orderlines):
if 'options' in orderline.keys():
options = orderline.pop('options')
orderline_list.append(
OrderLine(
**orderline,
order=order,
)
)

orderline_list[idx].save()

if 'options' in orderline.keys():
for option in options:
OrderLineBaseProduct.objects.create(
order_line=orderline_list[idx],
option_id=option.get('id'),
quantity=option.get('quantity'),
)
orderline_list[idx].save()

response = validate_coupon_for_order(coupon, order)
response['orderline'] = serializers.OrderLineSerializerNoOrder(
response['orderline'],
context={'request': request}
).data

except Exception as err:
raise err
finally:
# add rollback in finally, so it always rollback the data
transaction.savepoint_rollback(sid)

if response.get('valid_use', False):
response['orderline'].pop('url', None)
response['orderline'].pop('id', None)
response['orderline'].pop('order', None)
response['orderline'].pop('coupon', None)
response['orderline'].pop('coupon_real_value', None)
response['orderline'].pop('cost', None)
response.pop('valid_use', None)
response.pop('error', None)
return Response(response)
return Response(response['error'], status=status.HTTP_400_BAD_REQUEST)

return Response(response['error'],
status=status.HTTP_400_BAD_REQUEST)

def get_queryset(self):
"""
Expand Down

0 comments on commit e9abea1

Please sign in to comment.