Merge pull request #18 from JamesRamm/shipping

Shipping
pull/22/head
James Ramm 2017-02-12 16:25:50 +00:00 zatwierdzone przez GitHub
commit c9d9e1e5eb
41 zmienionych plików z 687 dodań i 203 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

@ -1,5 +1,6 @@
import braintree
from longclaw import settings
from longclaw.longclawsettings.models import LongclawSettings
from longclaw.checkout.utils import PaymentError
from longclaw.checkout.gateways import BasePayment
@ -38,11 +39,12 @@ class PaypalVZeroPayment():
self.gateway = braintree.BraintreeGateway(access_token=settings.VZERO_ACCESS_TOKEN)
def create_payment(self, request, amount, description=''):
longclaw_settings = LongclawSettings.for_site(request.site)
nonce = request.data['payment_method_nonce']
result = self.gateway.transaction.sale({
"amount": str(amount),
"payment_method_nonce": nonce,
"merchant_account_id": settings.CURRENCY,
"merchant_account_id": longclaw_settings.currency,
"options": {
"paypal": {
"description": description

Wyświetl plik

@ -1,6 +1,7 @@
import math
import stripe
from longclaw.settings import CURRENCY, STRIPE_SECRET
from longclaw.settings import STRIPE_SECRET
from longclaw.longclawsettings.models import LongclawSettings
from longclaw.checkout.utils import PaymentError
from longclaw.checkout.gateways import BasePayment
@ -14,9 +15,10 @@ class StripePayment(BasePayment):
def create_payment(self, request, amount):
try:
currency = LongclawSettings.for_site(request.site).currency
charge = stripe.Charge.create(
amount=int(math.ceil(amount * 100)), # Amount in pence
currency=CURRENCY.lower(),
currency=currency.lower(),
source=request.data['token'],
description="Payment from"
)

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,6 @@
from django.apps import AppConfig
class LongclawSettingsConfig(AppConfig):
name = 'longclawsettings'
verbose_name = 'Longclaw Settings'

Wyświetl plik

@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2017-02-12 14:22
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('wagtailcore', '0030_index_on_pagerevision_created_at'),
]
operations = [
migrations.CreateModel(
name='LongclawSettings',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('default_shipping_rate', models.DecimalField(decimal_places=2, help_text='The default shipping rate for countries which have not been configured', max_digits=12)),
('default_shipping_carrier', models.CharField(help_text='The default shipping carrier', max_length=32)),
('default_shipping_enabled', models.BooleanField(default=False, help_text='Whether to enable default shipping. This essentially means you ship to all countries, not only those with configured shipping rates')),
('site', models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, to='wagtailcore.Site')),
],
options={
'abstract': False,
},
),
]

Wyświetl plik

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2017-02-12 14:23
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('longclawsettings', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='longclawsettings',
name='default_shipping_carrier',
field=models.CharField(default='Royal Mail', help_text='The default shipping carrier', max_length=32),
),
migrations.AlterField(
model_name='longclawsettings',
name='default_shipping_rate',
field=models.DecimalField(decimal_places=2, default=3.95, help_text='The default shipping rate for countries which have not been configured', max_digits=12),
),
]

Wyświetl plik

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2017-02-12 15:03
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('longclawsettings', '0002_auto_20170212_1423'),
]
operations = [
migrations.AddField(
model_name='longclawsettings',
name='currency_html_code',
field=models.CharField(default='£', max_length=12),
),
]

Wyświetl plik

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2017-02-12 16:05
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('longclawsettings', '0003_longclawsettings_currency_html_code'),
]
operations = [
migrations.AddField(
model_name='longclawsettings',
name='currency',
field=models.CharField(default='GBP', max_length=6),
),
]

Wyświetl plik

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2017-02-12 16:09
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('longclawsettings', '0004_longclawsettings_currency'),
]
operations = [
migrations.AlterField(
model_name='longclawsettings',
name='currency',
field=models.CharField(default='GBP', help_text='The iso currency code to use for payments', max_length=6),
),
migrations.AlterField(
model_name='longclawsettings',
name='currency_html_code',
field=models.CharField(default='£', help_text='The HTML code for the currency symbol. Used for display purposes only', max_length=12),
),
]

Wyświetl plik

@ -0,0 +1,45 @@
'''
Admin confiurable settings for longclaw apps
'''
from wagtail.contrib.settings.models import BaseSetting, register_setting
from wagtail.wagtailadmin.edit_handlers import FieldPanel
from django.db import models
@register_setting
class LongclawSettings(BaseSetting):
default_shipping_rate = models.DecimalField(
default=3.95,
max_digits=12,
decimal_places=2,
help_text='The default shipping rate for countries which have not been configured'
)
default_shipping_carrier = models.CharField(
default="Royal Mail",
max_length=32,
help_text='The default shipping carrier'
)
default_shipping_enabled = models.BooleanField(
default=False,
help_text=('Whether to enable default shipping.'
' This essentially means you ship to all countries,'
' not only those with configured shipping rates'))
currency_html_code = models.CharField(
max_length=12,
default="£",
help_text="The HTML code for the currency symbol. Used for display purposes only"
)
currency = models.CharField(
max_length=6,
default="GBP",
help_text="The iso currency code to use for payments"
)
panels = (
FieldPanel('default_shipping_rate'),
FieldPanel('default_shipping_carrier'),
FieldPanel('default_shipping_enabled'),
FieldPanel('currency_html_code'),
FieldPanel('currency')
)

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

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2017-02-12 16:05
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0003_auto_20170211_1632'),
]
operations = [
migrations.AlterField(
model_name='order',
name='shipping_rate',
field=models.DecimalField(blank=True, decimal_places=2, max_digits=12, null=True),
),
]

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.settings import PRODUCT_VARIANT_MODEL
from longclaw.shipping.models import Address
class Order(models.Model):
SUBMITTED = 1
@ -45,7 +25,8 @@ class Order(models.Model):
shipping_rate = models.DecimalField(max_digits=12,
decimal_places=2,
default=DEFAULT_SHIPPING_RATE)
blank=True,
null=True)
@property
def total(self):

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

@ -3,21 +3,6 @@ Default settings for longclaw apps
'''
from django.conf import settings
# The currency to use for payments
CURRENCY = getattr(settings, "CURRENCY", "GBP")
# Default shipping rate to use when no configured ShippingCountry is found
# for a given address
DEFAULT_SHIPPING_RATE = getattr(settings, 'DEFAULT_SHIPPING_RATE', 3.95)
# Default carrier to use for the default rate
DEFAULT_SHIPPING_CARRIER = getattr(
settings, 'DEFAULT_SHIPPING_CARRIER', 'Royal Mail')
# Whether to fall back to using the default shipping rate if no ShippingCountry is found
# This means shipping worldwide
DEFAULT_SHIPPING_ENABLED = getattr(settings, 'DEFAULT_SHIPPING_ENABLED', True)
# The payment gateway backend to use
# Can be 'longclaw.checkout.gateways.BraintreePayment',
# 'longclaw.checkout.gateways.PaypalVZeroPayment',

Wyświetl plik

@ -0,0 +1,73 @@
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.longclawsettings.models import LongclawSettings
class InvalidShippingRate(Exception):
pass
class InvalidShippingCountry(Exception):
pass
def get_shipping_cost(country_code, option, settings):
try:
obj = models.ShippingCountry.objects.get(country_code=country_code)
try:
shipping_rate = obj.shipping_rates.get(name=option)
return {
"rate": shipping_rate.rate,
"description": shipping_rate.description,
"carrier": shipping_rate.carrier
}
except models.ShippingRate.DoesNotExist:
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_rate}
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_rate_name', 'standard')
try:
settings = LongclawSettings.for_site(request.site)
data = get_shipping_cost(code, option, settings)
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,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2017-02-11 17:06
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('shipping', '0001_initial'),
]
operations = [
migrations.AlterModelOptions(
name='shippingcountry',
options={'verbose_name_plural': 'shipping countries'},
),
]

Wyświetl plik

@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2017-02-11 21:29
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
import modelcluster.fields
class Migration(migrations.Migration):
dependencies = [
('wagtailcore', '0030_index_on_pagerevision_created_at'),
('shipping', '0002_auto_20170211_1706'),
]
operations = [
migrations.AddField(
model_name='shippingcountry',
name='page_ptr',
field=models.OneToOneField(auto_created=True, default=1, on_delete=django.db.models.deletion.CASCADE, parent_link=True, to='wagtailcore.Page'),
preserve_default=False,
),
migrations.AlterField(
model_name='shippingrate',
name='shipping_country',
field=modelcluster.fields.ParentalKey(on_delete=django.db.models.deletion.CASCADE, related_name='shipping_rates', to='shipping.ShippingCountry'),
),
]

Wyświetl plik

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2017-02-11 21:32
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('shipping', '0003_auto_20170211_2129'),
]
operations = [
migrations.RemoveField(
model_name='shippingcountry',
name='page_ptr',
),
migrations.AlterField(
model_name='shippingrate',
name='shipping_country',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='shipping_rates', to='shipping.ShippingCountry'),
),
]

Wyświetl plik

@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2017-02-11 21:38
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
import modelcluster.fields
class Migration(migrations.Migration):
dependencies = [
('wagtailcore', '0030_index_on_pagerevision_created_at'),
('shipping', '0004_auto_20170211_2132'),
]
operations = [
migrations.AddField(
model_name='shippingcountry',
name='page_ptr',
field=models.OneToOneField(auto_created=True, default=1, on_delete=django.db.models.deletion.CASCADE, parent_link=True, to='wagtailcore.Page'),
preserve_default=False,
),
migrations.AlterField(
model_name='shippingrate',
name='shipping_country',
field=modelcluster.fields.ParentalKey(on_delete=django.db.models.deletion.CASCADE, related_name='shipping_rates', to='shipping.ShippingCountry'),
),
]

Wyświetl plik

@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2017-02-11 21:49
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
import django_countries.fields
class Migration(migrations.Migration):
dependencies = [
('shipping', '0005_auto_20170211_2138'),
]
operations = [
migrations.RemoveField(
model_name='shippingcountry',
name='country_code',
),
migrations.RemoveField(
model_name='shippingcountry',
name='country_name',
),
migrations.AddField(
model_name='shippingcountry',
name='country',
field=django_countries.fields.CountryField(default='UK', max_length=2),
preserve_default=False,
),
migrations.AlterField(
model_name='shippingcountry',
name='page_ptr',
field=models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page'),
),
]

Wyświetl plik

@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2017-02-12 11:57
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('wagtailcore', '0030_index_on_pagerevision_created_at'),
('shipping', '0006_auto_20170211_2149'),
]
operations = [
migrations.CreateModel(
name='ShippingSettings',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('default_shipping_rate', models.DecimalField(decimal_places=2, help_text='The default shipping rate for countries which have not been configured', max_digits=12)),
('default_shipping_carrier', models.CharField(help_text='The default shipping carrier', max_length=32)),
('default_shipping_enabled', models.BooleanField(default=False, help_text='Whether to enable default shipping. This essentially means you ship to all countries, not only those with configured shipping rates')),
('site', models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, to='wagtailcore.Site')),
],
options={
'abstract': False,
},
),
]

Wyświetl plik

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2017-02-12 14:22
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('shipping', '0007_shippingsettings'),
]
operations = [
migrations.RemoveField(
model_name='shippingsettings',
name='site',
),
migrations.DeleteModel(
name='ShippingSettings',
),
]

Wyświetl plik

@ -0,0 +1,55 @@
from django.db import models
from modelcluster.fields import ParentalKey
from wagtail.wagtailcore.models import Page
from wagtail.wagtailadmin.edit_handlers import FieldPanel, InlinePanel
from django_countries.fields import CountryField
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(Page):
''' Standard and premimum rate shipping for
individual countries.
'''
parent_page_types = ['wagtailcore.Page']
country = CountryField()
content_panels = Page.content_panels + [
FieldPanel('country'),
InlinePanel('shipping_rates', label='Shipping rates')
]
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 = ParentalKey(
ShippingCountry, related_name="shipping_rates")
def __str__(self):
return self.name

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,24 @@
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 = True
list_display = ('country', 'country_code', 'shipping_rates')
def flag(self, obj):
return obj.country.flag
def country_code(self, obj):
return obj.country.alpha3
def shipping_rates(self, obj):
return ", ".join(str(rate) for rate in obj.shipping_rates.all())
modeladmin_register(ShippingCountryModelAdmin)

Wyświetl plik

@ -4,3 +4,4 @@ django-extensions
djangorestframework>=3.5.3
wagtail==1.7
simplejson==3.10.0
django-countries==4.0