wagtail-longclaw/longclaw/shipping/api.py

139 wiersze
5.1 KiB
Python

from django.db.models import Q
from rest_framework.decorators import api_view, permission_classes
from rest_framework import permissions, status, viewsets
from rest_framework.response import Response
from longclaw.shipping import models, utils, serializers
from longclaw.configuration.models import Configuration
from longclaw.basket.utils import basket_id
from .models import ShippingRateProcessor
from .signals import address_modified
class AddressViewSet(viewsets.ModelViewSet):
"""
Create, list and view Addresses
"""
queryset = models.Address.objects.all()
serializer_class = serializers.AddressSerializer
def perform_create(self, serializer):
output = super().perform_create(serializer)
instance = serializer.instance
address_modified.send(sender=models.Address, instance=instance)
def perform_update(self, serializer):
output = super().perform_update(serializer)
instance = serializer.instance
address_modified.send(sender=models.Address, instance=instance)
def perform_destroy(self, instance):
output = super().perform_destroy(instance)
address_modified.send(sender=models.Address, instance=instance)
def get_shipping_cost_kwargs(request, country=None):
country_code = request.query_params.get('country_code', None)
if country:
if country_code is not None:
raise utils.InvalidShippingCountry("Cannot specify country and country_code")
country_code = country
destination = request.query_params.get('destination', None)
if destination:
try:
destination = models.Address.objects.get(pk=destination)
except models.Address.DoesNotExist:
raise utils.InvalidShippingDestination("Address not found")
elif not country_code:
raise utils.InvalidShippingCountry("No country code supplied")
if not country_code:
country_code = destination.country.pk
bid = basket_id(request)
option = request.query_params.get('shipping_rate_name', 'standard')
settings = Configuration.for_site(request.site)
return dict(country_code=country_code, destination=destination, basket_id=bid, settings=settings, name=option)
@api_view(['GET'])
@permission_classes({permissions.AllowAny})
def shipping_cost(request):
""" Returns the shipping cost for a given country
If the shipping cost for the given country has not been set, it will
fallback to the default shipping cost if it has been enabled in the app
settings
"""
status_code = status.HTTP_400_BAD_REQUEST
try:
kwargs = get_shipping_cost_kwargs(request)
except (utils.InvalidShippingCountry, utils.InvalidShippingDestination) as e:
data = {'message': e.message}
else:
try:
data = utils.get_shipping_cost(**kwargs)
except utils.InvalidShippingRate:
data = {
"message": "Shipping option {} is invalid".format(kwargs['name'])
}
except utils.InvalidShippingCountry:
data = {
"message": "Shipping to {} is not available".format(kwargs['country_code'])
}
else:
status_code = status.HTTP_200_OK
return Response(data=data, status=status_code)
@api_view(["GET"])
@permission_classes([permissions.AllowAny])
def shipping_countries(request):
""" Get all shipping countries
"""
queryset = models.Country.objects.exclude(shippingrate=None)
serializer = serializers.CountrySerializer(queryset, many=True)
return Response(data=serializer.data, status=status.HTTP_200_OK)
@api_view(["GET"])
@permission_classes([permissions.AllowAny])
def shipping_options(request, country=None):
"""
Get the shipping options for a given country
"""
try:
kwargs = get_shipping_cost_kwargs(request, country=country)
except (utils.InvalidShippingCountry, utils.InvalidShippingDestination) as e:
return Response(data={'message': e.message}, status=status.HTTP_400_BAD_REQUEST)
country_code = kwargs['country_code']
settings = kwargs['settings']
bid = kwargs['basket_id']
destination = kwargs['destination']
processors = ShippingRateProcessor.objects.filter(countries__in=[country_code])
if processors:
if not destination:
return Response(
data={
"message": "Destination address is required for rates to {}.".format(country_code)
},
status=status.HTTP_400_BAD_REQUEST
)
for processor in processors:
processor.get_rates(settings=settings, basket_id=bid, destination=destination)
q = Q(countries__in=[country_code]) | Q(basket_id=bid, destination=None)
if destination:
q.add(Q(destination=destination, basket_id=''), Q.OR)
q.add(Q(destination=destination, basket_id=bid), Q.OR)
qrs = models.ShippingRate.objects.filter(q)
serializer = serializers.ShippingRateSerializer(qrs, many=True)
return Response(
data=serializer.data,
status=status.HTTP_200_OK
)