Separate shipping models and address and register with modeladmin

pull/18/head
JamesRamm 2017-02-11 17:06:19 +00:00
rodzic e2c6a7b8bf
commit 8b9867b740
20 zmienionych plików z 271 dodań i 183 usunięć

Wyświetl plik

@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2017-02-07 20:53
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('basket', '0001_initial'),
]
operations = [
migrations.RenameField(
model_name='basketitem',
old_name='product',
new_name='variant',
),
]

Wyświetl plik

@ -7,9 +7,8 @@ from rest_framework.decorators import api_view, permission_classes
from rest_framework import permissions, status
from rest_framework.response import Response
from longclaw.basket.utils import get_basket_items, destroy_basket
from longclaw.orders.models import Order, OrderItem, Address
from longclaw.checkout.models import ShippingCountry
from longclaw.checkout import serializers
from longclaw.orders.models import Order, OrderItem
from longclaw.shipping.models import Address
from longclaw.checkout.utils import PaymentError
from longclaw import settings
@ -95,7 +94,6 @@ def capture_payment(request):
)
order_item.save()
try:
gateway.create_payment(request, float(total)+postage)
# Once the order has been successfully taken, we can empty the basket
@ -108,70 +106,3 @@ def capture_payment(request):
response = Response(data={"message": err.message, "order_id": order.id},
status=status.HTTP_400_BAD_REQUEST)
return response
class InvalidShippingRate(Exception):
pass
class InvalidShippingCountry(Exception):
pass
def get_shipping_cost(country_code, option):
try:
obj = ShippingCountry.objects.get(country_code=country_code)
if option == 'standard':
return {"rate": obj.standard_rate,
"description": obj.standard_rate_description,
"carrier": obj.standard_rate_carrier}
elif option == 'premium':
return {"rate": obj.premium_rate,
"description": obj.premium_rate_description,
"carrier": obj.premium_rate_carrier}
else:
raise InvalidShippingRate
except ShippingCountry.DoesNotExist:
if settings.DEFAULT_SHIPPING_ENABLED:
return {"rate": settings.DEFAULT_SHIPPING_RATE,
"description": "Standard shipping to rest of world",
"carrier": settings.DEFAULT_SHIPPING_CARRIER}
else:
raise InvalidShippingCountry
@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
'''
try:
code = request.query_params.get('country_code')
except AttributeError:
return Response(data={"message": "No country code supplied"},
status=status.HTTP_400_BAD_REQUEST)
option = request.query_params.get('shipping_option', 'standard')
try:
data = get_shipping_cost(code, option)
response = Response(data=data, status=status.HTTP_200_OK)
except InvalidShippingRate:
response = Response(data={"message": "Shipping option {} is invalid".format(option)},
status=status.HTTP_400_BAD_REQUEST)
except InvalidShippingCountry:
response = Response(data={"message": "Shipping to {} is not available".format(code)},
status=status.HTTP_400_BAD_REQUEST)
return response
@api_view(["GET"])
@permission_classes([permissions.AllowAny])
def get_shipping_countries(request):
''' Get all shipping countries
'''
queryset = ShippingCountry.objects.all()
serializer = serializers.ShippingCountrySerializer(queryset, many=True)
return Response(data=serializer.data, status=status.HTTP_200_OK)

Wyświetl plik

@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2017-02-11 16:32
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('checkout', '0001_initial'),
]
operations = [
migrations.DeleteModel(
name='ShippingCountry',
),
]

Wyświetl plik

@ -1,17 +0,0 @@
from django.db import models
class ShippingCountry(models.Model):
''' Standard and premimum rate shipping for
individual countries.
'''
country_code = models.CharField(max_length=3, primary_key=True)
country_name = models.CharField(max_length=32)
standard_rate = models.DecimalField(max_digits=12, decimal_places=2)
standard_rate_carrier = models.CharField(max_length=64, default="Royal Mail")
standard_rate_description = models.CharField(max_length=128,
default="Royal Mail standard shipping")
premium_rate = models.DecimalField(max_digits=12, decimal_places=2)
premium_rate_carrier = models.CharField(max_length=64, default="Royal Mail")
premium_rate_description = models.CharField(max_length=128,
default="Royal Mail tracked and signed for")

Wyświetl plik

@ -1,12 +0,0 @@
from rest_framework import serializers
from longclaw.products.serializers import ProductVariantSerializer
from longclaw.checkout.models import ShippingCountry
class ShippingCountrySerializer(serializers.ModelSerializer):
class Meta:
model = ShippingCountry
fields = "__all__"

Wyświetl plik

@ -2,9 +2,6 @@ from django.conf.urls import url
from longclaw.checkout import api
urlpatterns = [
url(r'shipping/$',
api.shipping_cost,
name='shipping'),
url(r'payment/$',
api.capture_payment,
name='payment'),

Wyświetl plik

@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2017-02-11 16:32
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('shipping', '__first__'),
('orders', '0002_order_shipping_rate'),
]
operations = [
migrations.AlterField(
model_name='order',
name='billing_address',
field=models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, related_name='orders_billing_address', to='shipping.Address'),
),
migrations.AlterField(
model_name='order',
name='shipping_address',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='orders_shipping_address', to='shipping.Address'),
),
migrations.DeleteModel(
name='Address',
),
]

Wyświetl plik

@ -1,26 +1,6 @@
from django.db import models
from wagtail.wagtailadmin.edit_handlers import FieldPanel, InlinePanel
from longclaw.settings import PRODUCT_VARIANT_MODEL, DEFAULT_SHIPPING_RATE
class Address(models.Model):
name = models.CharField(max_length=64)
line_1 = models.CharField(max_length=128)
line_2 = models.CharField(max_length=128, blank=True)
city = models.CharField(max_length=64)
postcode = models.CharField(max_length=10)
country = models.CharField(max_length=32)
panels = [
FieldPanel('name'),
FieldPanel('line_1'),
FieldPanel('line_2'),
FieldPanel('city'),
FieldPanel('postcode'),
FieldPanel('country')
]
def __str__(self):
return "{}, {}, {}".format(self.name, self.city, self.country)
from longclaw.shipping.models import Address
class Order(models.Model):
SUBMITTED = 1

Wyświetl plik

@ -1,13 +1,8 @@
from django.apps import apps
from rest_framework import serializers
from longclaw.orders.models import Order, OrderItem, Address
from longclaw.orders.models import Order, OrderItem
from longclaw.products.serializers import ProductVariantSerializer
class AddressSerializer(serializers.ModelSerializer):
class Meta:
model = Address
fields = "__all__"
from longclaw.shipping.serializers import AddressSerializer
class OrderItemSerializer(serializers.ModelSerializer):

Wyświetl plik

@ -1,31 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2017-02-07 20:53
from __future__ import unicode_literals
from django.db import migrations
import django_extensions.db.fields
class Migration(migrations.Migration):
dependencies = [
('products', '0001_initial'),
]
operations = [
migrations.RenameField(
model_name='productimage',
old_name='page',
new_name='product',
),
migrations.RenameField(
model_name='productvariant',
old_name='page',
new_name='product',
),
migrations.AlterField(
model_name='productvariant',
name='slug',
field=django_extensions.db.fields.AutoSlugField(blank=True, editable=False, populate_from=('product', 'ref'), separator=''),
),
]

Wyświetl plik

@ -12,12 +12,13 @@ from wagtail.wagtailimages.edit_handlers import ImageChooserPanel
from wagtail.wagtailsearch import index
class ProductIndex(Page):
pass
subpage_types = ('products.Product',)
class ProductTag(TaggedItemBase):
content_object = ParentalKey('Product', related_name='tagged_items')
class Product(Page):
parent_page_types = ['products.ProductIndex']
description = RichTextField()
tags = ClusterTaggableManager(through=ProductTag, blank=True)

Wyświetl plik

@ -0,0 +1,72 @@
from rest_framework.decorators import api_view, permission_classes
from rest_framework import permissions, status
from rest_framework.response import Response
from longclaw.shipping import serializers, models
from longclaw import settings
class InvalidShippingRate(Exception):
pass
class InvalidShippingCountry(Exception):
pass
def get_shipping_cost(country_code, option):
try:
obj = models.ShippingCountry.objects.get(country_code=country_code)
if option == 'standard':
return {"rate": obj.standard_rate,
"description": obj.standard_rate_description,
"carrier": obj.standard_rate_carrier}
elif option == 'premium':
return {"rate": obj.premium_rate,
"description": obj.premium_rate_description,
"carrier": obj.premium_rate_carrier}
else:
raise InvalidShippingRate
except models.ShippingCountry.DoesNotExist:
if settings.DEFAULT_SHIPPING_ENABLED:
return {"rate": settings.DEFAULT_SHIPPING_RATE,
"description": "Standard shipping to rest of world",
"carrier": settings.DEFAULT_SHIPPING_CARRIER}
else:
raise InvalidShippingCountry
@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
'''
try:
code = request.query_params.get('country_code')
except AttributeError:
return Response(data={"message": "No country code supplied"},
status=status.HTTP_400_BAD_REQUEST)
option = request.query_params.get('shipping_option', 'standard')
try:
data = get_shipping_cost(code, option)
response = Response(data=data, status=status.HTTP_200_OK)
except InvalidShippingRate:
response = Response(data={"message": "Shipping option {} is invalid".format(option)},
status=status.HTTP_400_BAD_REQUEST)
except InvalidShippingCountry:
response = Response(data={"message": "Shipping to {} is not available".format(code)},
status=status.HTTP_400_BAD_REQUEST)
return response
@api_view(["GET"])
@permission_classes([permissions.AllowAny])
def shipping_countries(request):
''' Get all shipping countries
'''
queryset = models.ShippingCountry.objects.all()
serializer = serializers.ShippingCountrySerializer(queryset, many=True)
return Response(data=serializer.data, status=status.HTTP_200_OK)

Wyświetl plik

@ -0,0 +1,5 @@
from django.apps import AppConfig
class ShippingConfig(AppConfig):
name = 'shipping'

Wyświetl plik

@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2017-02-11 16:39
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Address',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=64)),
('line_1', models.CharField(max_length=128)),
('line_2', models.CharField(blank=True, max_length=128)),
('city', models.CharField(max_length=64)),
('postcode', models.CharField(max_length=10)),
('country', models.CharField(max_length=32)),
],
),
migrations.CreateModel(
name='ShippingCountry',
fields=[
('country_code', models.CharField(max_length=3, primary_key=True, serialize=False)),
('country_name', models.CharField(max_length=32)),
],
),
migrations.CreateModel(
name='ShippingRate',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=32)),
('rate', models.DecimalField(decimal_places=2, max_digits=12)),
('carrier', models.CharField(max_length=64)),
('description', models.CharField(max_length=128)),
('shipping_country', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='shipping_rates', to='shipping.ShippingCountry')),
],
),
]

Wyświetl plik

@ -0,0 +1,41 @@
from django.db import models
from wagtail.wagtailadmin.edit_handlers import FieldPanel, InlinePanel
class Address(models.Model):
name = models.CharField(max_length=64)
line_1 = models.CharField(max_length=128)
line_2 = models.CharField(max_length=128, blank=True)
city = models.CharField(max_length=64)
postcode = models.CharField(max_length=10)
country = models.CharField(max_length=32)
panels = [
FieldPanel('name'),
FieldPanel('line_1'),
FieldPanel('line_2'),
FieldPanel('city'),
FieldPanel('postcode'),
FieldPanel('country')
]
def __str__(self):
return "{}, {}, {}".format(self.name, self.city, self.country)
class ShippingCountry(models.Model):
''' Standard and premimum rate shipping for
individual countries.
'''
country_code = models.CharField(max_length=3, primary_key=True)
country_name = models.CharField(max_length=32)
class Meta:
verbose_name_plural = "shipping countries"
class ShippingRate(models.Model):
name = models.CharField(max_length=32)
rate = models.DecimalField(max_digits=12, decimal_places=2)
carrier = models.CharField(max_length=64)
description = models.CharField(max_length=128)
shipping_country = models.ForeignKey(ShippingCountry, related_name="shipping_rates")

Wyświetl plik

@ -0,0 +1,24 @@
from rest_framework import serializers
from longclaw.shipping.models import Address, ShippingCountry, ShippingRate
class AddressSerializer(serializers.ModelSerializer):
class Meta:
model = Address
fields = "__all__"
class ShippingRateSerializer(serializers.ModelSerializer):
class Meta:
model = ShippingRate
fields = "__all__"
class ShippingCountrySerializer(serializers.ModelSerializer):
shipping_rates = ShippingRateSerializer(many=True)
class Meta:
model = ShippingCountry
fields = "__all__"

Wyświetl plik

@ -0,0 +1,11 @@
from django.conf.urls import url
from longclaw.shipping import api
urlpatterns = [
url(r'shipping/cost/$',
api.shipping_cost,
name='shipping_cost'),
url(r'shipping/countries/$',
api.shipping_countries,
name="shipping_countries")
]

Wyświetl plik

@ -0,0 +1,16 @@
from wagtail.contrib.modeladmin.options import (
ModelAdmin, modeladmin_register
)
from longclaw.shipping.models import ShippingCountry
class ShippingCountryModelAdmin(ModelAdmin):
model = ShippingCountry
menu_order = 200
menu_icon = 'site'
add_to_settings_menu = False
exclude_from_explorer = False
list_display = ('country_name', 'country_code')
inspect_view_enabled = True
modeladmin_register(ShippingCountryModelAdmin)