product varient change list bug fix order item change quantity and remove

This commit is contained in:
Parsa Nazer
2025-02-15 00:08:16 +03:30
parent 00b5ce5a6c
commit 81d75d61e7
16 changed files with 264 additions and 14 deletions
+1
View File
@@ -25,6 +25,7 @@ urlpatterns = [
path('chat/', include('chat.urls')), path('chat/', include('chat.urls')),
path('tickets/', include('ticket.urls')), path('tickets/', include('ticket.urls')),
path('blogs/', include('blog.urls')), path('blogs/', include('blog.urls')),
path('order/', include('order.urls')),
path('', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'), path('', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'),
] ]
+2
View File
@@ -0,0 +1,2 @@
class DiscountNotAvailableError(Exception):
pass
@@ -0,0 +1,20 @@
# Generated by Django 5.1.2 on 2025-02-13 20:07
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('order', '0003_alter_orderitemmodel_product'),
('product', '0023_alter_productimagemodel_options_and_more'),
]
operations = [
migrations.AlterField(
model_name='orderitemmodel',
name='product',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='product.productvariant', verbose_name='محصول'),
),
]
+11 -8
View File
@@ -1,8 +1,8 @@
from django.db import models from django.db import models
from account.models import User, UserAddressModel from account.models import User, UserAddressModel
from product.models import ProductModel from product.models import ProductModel, ProductVariant
from django.utils import timezone from django.utils import timezone
from .execptions import DiscountNotAvailableError
class DiscountCode(models.Model): class DiscountCode(models.Model):
name = models.CharField(max_length=50, verbose_name='کد تخفیف') name = models.CharField(max_length=50, verbose_name='کد تخفیف')
percent = models.DecimalField(max_digits=4, decimal_places=2, verbose_name='درصد') percent = models.DecimalField(max_digits=4, decimal_places=2, verbose_name='درصد')
@@ -43,13 +43,15 @@ class OrderModel(models.Model):
verbose_name = 'سفارش' verbose_name = 'سفارش'
verbose_name_plural = 'سفارشات' verbose_name_plural = 'سفارشات'
def total_without_tax(self): # def total_without_tax(self):
return sum(item.total() for item in self.items.all()) # return sum(item.total() for item in self.items.all())
def total_with_discount(self): def total_with_discount(self):
total_with_item_discount = sum(item.total_with_discount() for item in self.items.all()) total_with_item_discount = sum(item.total_with_discount() for item in self.items.all())
if self.discount_code and self.discount_code.is_valid(): if self.discount_code:
if not self.discount_code.is_valid():
raise DiscountNotAvailableError('این کد تخفیف دیگر معتبر نیست')
discount_percent = self.discount_code.percent discount_percent = self.discount_code.percent
return total_with_item_discount * ((100 - discount_percent) / 100) return total_with_item_discount * ((100 - discount_percent) / 100)
return total_with_item_discount return total_with_item_discount
@@ -59,7 +61,7 @@ class OrderModel(models.Model):
return self.total_without_tax() * 0.2 return self.total_without_tax() * 0.2
def total(self): def total(self):
return self.total_without_tax + self.tax() return self.total_with_discount() + self.tax()
def remove_order_item(self, item_pk, quantity): def remove_order_item(self, item_pk, quantity):
pass pass
@@ -75,7 +77,7 @@ class OrderModel(models.Model):
class OrderItemModel(models.Model): class OrderItemModel(models.Model):
order = models.ForeignKey(OrderModel, on_delete=models.CASCADE, related_name='items', verbose_name='سفارش') order = models.ForeignKey(OrderModel, on_delete=models.CASCADE, related_name='items', verbose_name='سفارش')
quantity = models.SmallIntegerField(verbose_name="تعداد") quantity = models.SmallIntegerField(verbose_name="تعداد")
product = models.ForeignKey(ProductModel, on_delete=models.PROTECT, verbose_name="محصول") product = models.ForeignKey(ProductVariant, on_delete=models.PROTECT, verbose_name="محصول")
class Meta: class Meta:
verbose_name = 'محصول خریداری شده' verbose_name = 'محصول خریداری شده'
verbose_name_plural = 'محصولات خریداری شده' verbose_name_plural = 'محصولات خریداری شده'
@@ -85,5 +87,6 @@ class OrderItemModel(models.Model):
def total_with_discount(self): def total_with_discount(self):
return self.quantity * self.product.get_toman_price_after_discount() return self.quantity * self.product.get_toman_price_after_discount()
def __str__(self):
return f'ایتم سبد خرید محصول: {self.product} کاربر {self.order.user}'
+9
View File
@@ -0,0 +1,9 @@
from rest_framework import serializers
from .models import OrderItemModel
class OrderItemSerailzier(serializers.ModelSerializer):
class Meta:
model = OrderItemModel
fields = "__all__"
read_only_fields = ('order', 'product')
+8
View File
@@ -0,0 +1,8 @@
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path, include
from .views import CartItemViews
urlpatterns = [
path('cart/item/<int:pk>', CartItemViews.as_view(), name='add cart'),
]
+66 -1
View File
@@ -1,3 +1,68 @@
from django.shortcuts import render from django.shortcuts import render
from .execptions import DiscountNotAvailableError
from rest_framework.views import APIView, Response
from django.shortcuts import get_object_or_404
from product.models import ProductVariant
from rest_framework.permissions import IsAuthenticated
from .serializers import OrderItemSerailzier
# from cart.models import
from rest_framework import status
from .models import OrderItemModel, OrderModel
try:
pass
except DiscountNotAvailableError:
pass
# Create your views here. """
add post
remove delete
show get
pay
"""
class CartItemViews(APIView):
permission_classes = [IsAuthenticated]
serializer_class = OrderItemSerailzier
def post(self, request, pk):
product_variant = get_object_or_404(ProductVariant, pk=pk)
cart_order, created = OrderModel.objects.get_or_create(
user=request.user,
status='CART'
)
order_item, created = OrderItemModel.objects.get_or_create(
order=cart_order,
product=product_variant,
defaults={'quantity': request.data.get('quantity', 1)}
)
if not created:
order_item.quantity = request.data.get('quantity', 1)
order_item.save()
return Response({'detail': 'it did something'}, status=status.HTTP_201_CREATED)
def delete(self, request, pk):
product_variant = get_object_or_404(ProductVariant, pk=pk)
cart_order, created = OrderModel.objects.get_or_create(
user=request.user,
status='CART'
)
# order_item, created = OrderItemModel.objects.get_or_create(
# order=cart_order,
# product=product_variant,
# defaults={'quantity': request.data.get('quantity', 1)}
# )
order_item = get_object_or_404(OrderItemModel, order=cart_order, product=product_variant)
order_item.delete()
return Response({'detail': 'it did something related to delete'}, status=status.HTTP_204_NO_CONTENT)
class CartViews(APIView):
def get(self, request):
pass
+2 -2
View File
@@ -15,7 +15,7 @@ from unfold.decorators import action, display
class ProductVariantAdmin(ModelAdmin, ImportExportModelAdmin): class ProductVariantAdmin(ModelAdmin, ImportExportModelAdmin):
import_form_class = ImportForm import_form_class = ImportForm
export_form_class = ExportForm export_form_class = ExportForm
autocomplete_fields = ['attributes'] autocomplete_fields = ['product_attributes', 'images', 'in_pack_items']
warn_unsaved_form = True warn_unsaved_form = True
@@ -105,7 +105,7 @@ class ProductVariantInLine(StackedInline):
show_change_link = True show_change_link = True
tab = True tab = True
min_num = 1 min_num = 1
autocomplete_fields = ['attributes', 'in_pack_items', 'images'] autocomplete_fields = ['product_attributes', 'in_pack_items', 'images']
# search_fields = [''] # search_fields = ['']
@@ -0,0 +1,17 @@
# Generated by Django 5.1.2 on 2025-02-13 20:35
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('product', '0023_alter_productimagemodel_options_and_more'),
]
operations = [
migrations.AlterUniqueTogether(
name='attributevalue',
unique_together=set(),
),
]
@@ -0,0 +1,22 @@
# Generated by Django 5.1.2 on 2025-02-13 20:39
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('product', '0024_alter_attributevalue_unique_together'),
]
operations = [
migrations.AlterField(
model_name='productvariant',
name='attributes',
field=models.ManyToManyField(blank=True, related_name='variant', to='product.attributevalue', verbose_name='ویژگی\u200cها'),
),
migrations.AlterUniqueTogether(
name='attributevalue',
unique_together={('attribute_type', 'value')},
),
]
@@ -0,0 +1,18 @@
# Generated by Django 5.1.2 on 2025-02-13 20:40
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('product', '0025_alter_productvariant_attributes_and_more'),
]
operations = [
migrations.AlterField(
model_name='productvariant',
name='attributes',
field=models.ManyToManyField(related_name='variant', to='product.attributevalue', verbose_name='ویژگی\u200cها'),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 5.1.2 on 2025-02-13 20:41
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('product', '0026_alter_productvariant_attributes'),
]
operations = [
migrations.AlterField(
model_name='productvariant',
name='attributes',
field=models.ManyToManyField(blank=True, related_name='variant', to='product.attributevalue', verbose_name='ویژگی\u200cها'),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 5.1.2 on 2025-02-13 20:45
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('product', '0027_alter_productvariant_attributes'),
]
operations = [
migrations.AlterField(
model_name='productvariant',
name='attributes',
field=models.ManyToManyField(related_name='variant', to='product.attributevalue', verbose_name='ویژگی\u200cها'),
),
]
@@ -0,0 +1,21 @@
# Generated by Django 5.1.2 on 2025-02-13 20:48
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('product', '0028_alter_productvariant_attributes'),
]
operations = [
migrations.AlterUniqueTogether(
name='attributevalue',
unique_together=set(),
),
migrations.RemoveField(
model_name='attributevalue',
name='attribute_type',
),
]
@@ -0,0 +1,28 @@
# Generated by Django 5.1.2 on 2025-02-13 20:49
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('product', '0029_alter_attributevalue_unique_together_and_more'),
]
operations = [
migrations.RenameField(
model_name='productvariant',
old_name='attributes',
new_name='product_attributes',
),
migrations.AddField(
model_name='attributevalue',
name='attribute_type',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='product.attributetype'),
),
migrations.AlterUniqueTogether(
name='attributevalue',
unique_together={('attribute_type', 'value')},
),
]
+3 -3
View File
@@ -201,7 +201,7 @@ class AttributeValue(models.Model):
unique_together = ('attribute_type', 'value') unique_together = ('attribute_type', 'value')
def __str__(self): def __str__(self):
return f"{self.attribute_type.name}: {self.value}" return f"{self.attribute_type}: {self.value}"
class ProductImageModel(models.Model): class ProductImageModel(models.Model):
@@ -220,7 +220,7 @@ class ProductImageModel(models.Model):
class ProductVariant(models.Model): class ProductVariant(models.Model):
product = models.ForeignKey(ProductModel, on_delete=models.CASCADE, related_name='variants', verbose_name='محصول') product = models.ForeignKey(ProductModel, on_delete=models.CASCADE, related_name='variants', verbose_name='محصول')
attributes = models.ManyToManyField(AttributeValue, verbose_name='ویژگی‌ها', related_name='variant') product_attributes = models.ManyToManyField(AttributeValue, verbose_name='ویژگی‌ها', related_name='variant')
in_stock = models.PositiveIntegerField(default=0, verbose_name='تعداد موجود') in_stock = models.PositiveIntegerField(default=0, verbose_name='تعداد موجود')
price = models.PositiveIntegerField(default=0, verbose_name='قیمت') price = models.PositiveIntegerField(default=0, verbose_name='قیمت')
min_price = models.PositiveIntegerField(verbose_name='قیمت کف', help_text='این قیمت برای کف قیمتی محصول در نظر گرفته میشود') min_price = models.PositiveIntegerField(verbose_name='قیمت کف', help_text='این قیمت برای کف قیمتی محصول در نظر گرفته میشود')
@@ -242,7 +242,7 @@ class ProductVariant(models.Model):
verbose_name_plural = 'تنوع‌های محصول' verbose_name_plural = 'تنوع‌های محصول'
def __str__(self): def __str__(self):
return f"{self.product.name} - {', '.join(str(attr) for attr in self.attributes.all())}" return f"{self.product.name} - {', '.join(str(attr) for attr in self.product_attributes.all())}"
def get_toman_price(self, dollor_price=None): def get_toman_price(self, dollor_price=None):
if not dollor_price: if not dollor_price: