Skip to content

Commit 50b5d33

Browse files
Finished Chapter 11, this will be the final push insha'a allah,
1 parent 8f3a67c commit 50b5d33

File tree

19 files changed

+204
-71
lines changed

19 files changed

+204
-71
lines changed

cart/forms.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
from django import forms
2-
2+
from django.utils.translation import gettext_lazy as _
33
PRODUCT_QUANTITY_CHOICES = [(i, str(i)) for i in range(1, 21)]
44

55

66
class CartAddProductForm(forms.Form):
77
quantity = forms.TypedChoiceField(
88
choices=PRODUCT_QUANTITY_CHOICES,
99
coerce=int,
10+
label=_('Quantity'),
1011
)
1112
override = forms.BooleanField(
1213
required=False,

cart/views.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,12 @@ def cart_detail(request):
3737
'override': True,
3838
}
3939
)
40-
cart_products = [item for item in cart]
40+
cart_products = [item['product'] for item in cart]
4141
if cart_products:
4242
r = Recommender()
4343
recommended_products = r.suggest_products_for(cart_products, 4)
44-
recommended_products = []
44+
else:
45+
recommended_products = []
4546
coupon_apply_form = CouponApplyForm()
4647
return render(
4748
request,

coupons/froms.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
from django import forms
2+
from django.utils.translation import gettext_lazy as _
23

34

45
class CouponApplyForm(forms.Form):
5-
code = forms.CharField(max_length=50)
6+
code = forms.CharField(
7+
max_length=50,
8+
label=_('Coupon'),
9+
)

coupons/urls.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
from django.urls import path
2+
from django.utils.translation import gettext_lazy as _
23

34
from . import views
45

56
app_name = 'coupons'
67

78
urlpatterns = [
8-
path('apply/', views.coupon_apply, name='apply'),
9+
path(_('apply/'), views.coupon_apply, name='apply'),
910
]

myshop/settings/local.py

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
from pathlib import Path
1313

1414
from decouple import config
15+
from django.utils.translation import gettext_lazy as _
16+
17+
# from django.conf.global_settings import LOCALE_PATHS
1518

1619
# Build paths inside the project like this: BASE_DIR / 'subdir'.
1720
BASE_DIR = Path(__file__).resolve().parent.parent
@@ -42,11 +45,15 @@
4245
'orders.apps.OrdersConfig',
4346
'payment.apps.PaymentConfig',
4447
'coupons.apps.CouponsConfig',
48+
'rosetta',
49+
'parler',
50+
'localflavor',
4551
]
4652

4753
MIDDLEWARE = [
4854
'django.middleware.security.SecurityMiddleware',
4955
'django.contrib.sessions.middleware.SessionMiddleware',
56+
'django.middleware.locale.LocaleMiddleware',
5057
'django.middleware.common.CommonMiddleware',
5158
'django.middleware.csrf.CsrfViewMiddleware',
5259
'django.contrib.auth.middleware.AuthenticationMiddleware',
@@ -110,7 +117,11 @@
110117
# Internationalization
111118
# https://docs.djangoproject.com/en/5.1/topics/i18n/
112119

113-
LANGUAGE_CODE = 'en-us'
120+
LANGUAGE_CODE = 'en'
121+
LANGUAGES = [
122+
('en', _('English')),
123+
('ar', _('Arabic'))
124+
]
114125

115126
TIME_ZONE = 'UTC'
116127

@@ -150,8 +161,22 @@
150161

151162
STRIPE_WEBHOOK_SECRET = config('STRIPE_WEBHOOK_SECRET')
152163

153-
154164
# Redis settings
155165
REDIS_HOST = 'localhost'
156166
REDIS_PORT = 6379
157-
REDIS_DB = 1
167+
REDIS_DB = 1
168+
169+
LOCALE_PATHS = [
170+
BASE_DIR / 'locale'
171+
]
172+
173+
PARLER_LANGUAGES = {
174+
None: (
175+
{'code': 'en'},
176+
{'code': 'ar'},
177+
),
178+
'default': {
179+
'fallback': 'en',
180+
'hide_untranslated': False,
181+
}
182+
}

myshop/settings/production.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
MIDDLEWARE = [
4949
'django.middleware.security.SecurityMiddleware',
5050
'django.contrib.sessions.middleware.SessionMiddleware',
51+
'django.middleware.locale.LocaleMiddleware',
5152
'django.middleware.common.CommonMiddleware',
5253
'django.middleware.csrf.CsrfViewMiddleware',
5354
'django.contrib.auth.middleware.AuthenticationMiddleware',
@@ -111,7 +112,11 @@
111112
# Internationalization
112113
# https://docs.djangoproject.com/en/5.1/topics/i18n/
113114

114-
LANGUAGE_CODE = 'en-us'
115+
LANGUAGE_CODE = 'en'
116+
LANGUAGES = [
117+
('en', 'English'),
118+
('ar', 'Arabic')
119+
]
115120

116121
TIME_ZONE = 'UTC'
117122

myshop/urls.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,26 @@
1515
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
1616
"""
1717
from django.conf import settings
18+
from django.conf.urls.i18n import i18n_patterns
1819
from django.conf.urls.static import static
1920
from django.contrib import admin
2021
from django.urls import path, include
22+
from django.utils.translation import gettext_lazy as _
2123

22-
urlpatterns = [
24+
from payment.webhooks import stripe_webhook
25+
26+
urlpatterns = i18n_patterns(
2327
path('admin/', admin.site.urls),
24-
path('cart/', include('cart.urls', namespace='cart')),
25-
path('orders/', include('orders.urls', namespace='orders')),
26-
path('payment/', include('payment.urls', namespace='payment')),
27-
path('coupons/', include('coupons.urls', namespace='coupons')),
28+
path(_('cart/'), include('cart.urls', namespace='cart')),
29+
path(_('orders/'), include('orders.urls', namespace='orders')),
30+
path(_('payment/'), include('payment.urls', namespace='payment')),
31+
path(_('coupons/'), include('coupons.urls', namespace='coupons')),
32+
path('rosetta/', include('rosetta.urls')),
2833
path('', include('shop.url', namespace='shop')),
34+
)
35+
36+
urlpatterns += [
37+
path('payment/webhook/', stripe_webhook, name='stripe-webhook'),
2938
]
3039

3140
if settings.DEBUG:

orders/forms.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
from django import forms
2+
from localflavor.us.forms import USZipCodeField
23

34
from .models import Order
45

56

67
class OrderCreateForm(forms.ModelForm):
8+
postal_code = USZipCodeField()
9+
710
class Meta:
811
model = Order
912
fields = [

orders/models.py

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,18 @@
33
from django.conf import settings
44
from django.core.validators import MaxValueValidator, MinValueValidator
55
from django.db import models
6+
from django.utils.translation import gettext_lazy as _
67

78
from coupons.models import Coupon
89

910

1011
class Order(models.Model):
11-
first_name = models.CharField(max_length=50)
12-
last_name = models.CharField(max_length=50)
13-
email = models.EmailField()
14-
address = models.CharField(max_length=250)
15-
postal_code = models.CharField(max_length=20)
16-
city = models.CharField(max_length=100)
12+
first_name = models.CharField(_('first name'), max_length=50)
13+
last_name = models.CharField(_('last name'), max_length=50)
14+
email = models.EmailField(_('e-mail'), )
15+
address = models.CharField(_('address'), max_length=250)
16+
postal_code = models.CharField(_('postal code'), max_length=20)
17+
city = models.CharField(_('city'), max_length=100)
1718
created = models.DateTimeField(auto_now_add=True)
1819
updated = models.DateTimeField(auto_now=True)
1920
paid = models.BooleanField(default=False)
@@ -57,7 +58,23 @@ def get_discount(self):
5758

5859
def get_total_cost(self):
5960
total_cost = self.get_total_cost_before_discount()
60-
return total_cost - self.get_discount()
61+
return total_cost - self.get_discount() + self.get_shipping_cost()
62+
63+
def get_total_weight(self):
64+
return sum(
65+
item.get_weight() for item in self.items.all()
66+
)
67+
68+
def get_shipping_cost(self):
69+
total_weight = self.get_total_weight()
70+
71+
# Define your shipping pricing rules based on weight
72+
if total_weight <= 1000: # 1 kg
73+
return Decimal(5) # Example: $5 for orders up to 1kg
74+
elif total_weight <= 5000: # 5 kg
75+
return Decimal(10) # Example: $10 for orders up to 5kg
76+
else:
77+
return Decimal(20) # Example: $20 for orders over 5kg
6178

6279
def get_stripe_url(self):
6380
if not self.stripe_id:
@@ -96,3 +113,6 @@ def __str__(self):
96113

97114
def get_cost(self):
98115
return self.price * self.quantity
116+
117+
def get_weight(self):
118+
return self.product.weight * self.quantity
Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
{% extends "shop/base.html" %}
2+
{% load i18n %}
23
{% block title %}
34
Checkout
45
{% endblock %}
56
{% block content %}
6-
<h1>Checkout</h1>
7+
<h1>{% translate 'Checkout' %}</h1>
78
<div class="order-info">
8-
<h3>Your order</h3>
9+
<h3>{% translate 'Your order' %}</h3>
910
<ul>
1011
{% for item in cart %}
1112
<li>
@@ -16,15 +17,18 @@ <h3>Your order</h3>
1617
{% if cart.coupon %}
1718
<li>
1819
"{{ cart.coupon.code }}" ({{ cart.coupon.discount }}% off)
20+
{% blocktranslate with code=cart.coupon.code discount=cart.coupon.discount %}
21+
"{{ code }}" ({{ discount }}% off)
22+
{% endblocktranslate %}
1923
<span class="neg">- ${{ cart.get_discount|floatformat:2 }}</span>
2024
</li>
2125
{% endif %}
2226
</ul>
23-
<p>Total: ${{ cart.get_total_price_after_discount|floatformat:2 }}</p>
27+
<p>{% translate 'Total' %}: ${{ cart.get_total_price_after_discount|floatformat:2 }}</p>
2428
</div>
2529
<form method="post" class="order-form">
2630
{{ form.as_p }}
27-
<p><input type="submit" value="Place order"></p>
31+
<p><input type="submit" value="{% translate 'Place order' %}"></p>
2832
{% csrf_token %}
2933
</form>
3034
{% endblock %}

0 commit comments

Comments
 (0)