fix order model invoice genrator
This commit is contained in:
@@ -9,7 +9,7 @@ from django.template.loader import render_to_string
|
||||
from weasyprint import HTML
|
||||
from django.conf import settings
|
||||
import jdatetime
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
def generate_order_invoice(order_id):
|
||||
"""
|
||||
@@ -30,33 +30,26 @@ def generate_order_invoice(order_id):
|
||||
except OrderModel.DoesNotExist:
|
||||
raise ValueError(f"Order with ID {order_id} does not exist")
|
||||
|
||||
# Prepare items with calculated discount amounts
|
||||
# Prepare items with calculated discount amounts using stored values
|
||||
items = order.items.all()
|
||||
items_with_discount = []
|
||||
total_items_discount = 0
|
||||
|
||||
for item in items:
|
||||
# Calculate the discount amount from the discount_percent
|
||||
# price is after discount, so we need to calculate original price
|
||||
# original_price = price / (1 - discount_percent/100)
|
||||
# discount_amount = original_price - price
|
||||
if item.discount_percent > 0:
|
||||
discount_multiplier = (100 - item.discount_percent) / 100
|
||||
price_after_discount = item.price
|
||||
price_before_discount = int(price_after_discount / discount_multiplier) if discount_multiplier > 0 else price_after_discount
|
||||
item_discount_amount = (price_before_discount - price_after_discount)
|
||||
else:
|
||||
item_discount_amount = 0
|
||||
price_before_discount = item.price
|
||||
total_items_discount += item.total_product_discount_amount() or 0
|
||||
|
||||
items_with_discount.append({
|
||||
'item': item,
|
||||
'discount_amount': item_discount_amount,
|
||||
'price_before_discount': price_before_discount
|
||||
'discount_amount': item.total_product_discount_amount() or 0,
|
||||
'price_before_discount': item.total_price_before_discount(),
|
||||
'unit_price': item.unit_price(),
|
||||
'final_price': item.price_after_special_discount(),
|
||||
})
|
||||
|
||||
# Prepare context for the template
|
||||
# Use stored model fields for accuracy and consistency
|
||||
context = {
|
||||
'order': order,
|
||||
'order_number': order.pk + 1000,
|
||||
'order_number': order.pk,
|
||||
'items': items,
|
||||
'items_with_discount': items_with_discount,
|
||||
'user': order.user,
|
||||
@@ -64,11 +57,13 @@ def generate_order_invoice(order_id):
|
||||
'discount_code': order.discount_code,
|
||||
'created_at_jalali': jdatetime.datetime.fromgregorian(datetime=order.created_at) if order.created_at else None,
|
||||
'total_items': sum(item.quantity for item in items),
|
||||
'subtotal': order.cart_total,
|
||||
'discount_amount': order.discount_amount or 0,
|
||||
'special_discount_total': order.special_discount_total or 0,
|
||||
'tax': order.tax or 0,
|
||||
'final_price': order.final_price,
|
||||
'subtotal': order.cart_total or 0, # Stored field: total before any discounts
|
||||
'items_discount_amount': total_items_discount,
|
||||
'discount_amount': order.discount_amount or 0, # Stored field: discount code amount
|
||||
'special_discount_total': order.special_discount_total or 0, # Stored field: special discount total
|
||||
'tax_rate': settings.DEFAULT_TAX_RATE,
|
||||
'tax': order.tax or 0, # Stored field: tax amount
|
||||
'final_price': order.final_price or 0, # Stored field: final price after all calculations
|
||||
'is_paid': order.is_paid,
|
||||
'status': order.get_status_display(),
|
||||
}
|
||||
@@ -104,7 +99,32 @@ def generate_shop_order_invoice(shop_order_id):
|
||||
except ShopOrderModel.DoesNotExist:
|
||||
raise ValueError(f"ShopOrder with ID {shop_order_id} does not exist")
|
||||
|
||||
# Calculate total before any discount from shop order items
|
||||
# shop_order.subtotal stores price AFTER product discount, so we need to recalculate
|
||||
items = shop_order.items.select_related('order_item').all()
|
||||
total_before_any_discount = 0
|
||||
total_product_discount = 0
|
||||
|
||||
for shop_item in items:
|
||||
order_item = shop_item.order_item
|
||||
# order_item.price is unit price AFTER product discount
|
||||
if order_item.discount_percent > 0:
|
||||
discount_multiplier = (100 - order_item.discount_percent) / 100
|
||||
if discount_multiplier > 0:
|
||||
price_before_discount_unit = int(order_item.price / discount_multiplier)
|
||||
else:
|
||||
price_before_discount_unit = order_item.price
|
||||
|
||||
item_discount = (price_before_discount_unit - order_item.price) * shop_item.quantity
|
||||
total_product_discount += item_discount
|
||||
else:
|
||||
price_before_discount_unit = order_item.price
|
||||
|
||||
total_before_any_discount += price_before_discount_unit * shop_item.quantity
|
||||
|
||||
# Prepare context for the template
|
||||
subtotal_after_discount = total_before_any_discount - (total_product_discount + shop_order.special_discount_amount) + shop_order.tax_amount
|
||||
|
||||
context = {
|
||||
'shop_order': shop_order,
|
||||
'order_number': shop_order.order.pk + 1000,
|
||||
@@ -119,12 +139,13 @@ def generate_shop_order_invoice(shop_order_id):
|
||||
'address_city': shop_order.address_city,
|
||||
'address_province': shop_order.address_province,
|
||||
'address_recipient_name': shop_order.address_recipient_name,
|
||||
'items': shop_order.items.all(),
|
||||
'items': items,
|
||||
'created_at_jalali': jdatetime.datetime.fromgregorian(datetime=shop_order.order_created_at) if shop_order.order_created_at else None,
|
||||
'total_items': shop_order.items_count,
|
||||
'subtotal': shop_order.subtotal,
|
||||
'discount_amount': shop_order.discount_amount,
|
||||
'subtotal': total_before_any_discount, # Total BEFORE any discount
|
||||
'discount_amount': total_product_discount, # Product discount amount
|
||||
'special_discount_amount': shop_order.special_discount_amount,
|
||||
'subtotal_after_discount': subtotal_after_discount,
|
||||
'tax_amount': shop_order.tax_amount,
|
||||
'commission_percent': shop_order.commission_percent,
|
||||
'commission_amount': shop_order.commission_amount,
|
||||
|
||||
@@ -251,6 +251,24 @@ class OrderItemModel(models.Model):
|
||||
def __str__(self):
|
||||
return f'({self.product}) - ({self.order.user})'
|
||||
|
||||
# @property
|
||||
def total_price_before_discount(self):
|
||||
return self.price * self.quantity
|
||||
|
||||
# @property
|
||||
def total_product_discount_amount(self):
|
||||
if self.discount_percent > 0:
|
||||
return int((self.price * self.quantity) * (self.discount_percent / 100))
|
||||
return 0
|
||||
|
||||
# @property
|
||||
def price_after_special_discount(self):
|
||||
all_discounts = (self.special_discount_amount or 0) + self.total_product_discount_amount()
|
||||
print(all_discounts)
|
||||
return self.total_price_before_discount() - all_discounts
|
||||
|
||||
def unit_price(self):
|
||||
return self.price
|
||||
|
||||
class ShopOrderModel(models.Model):
|
||||
"""Represents the portion of a customer Order that belongs to a single Shop.
|
||||
|
||||
@@ -264,7 +264,8 @@
|
||||
<th>نام محصول</th>
|
||||
<th>تنوع</th>
|
||||
<th>تعداد</th>
|
||||
<th>قیمت اصلی</th>
|
||||
<th>قیمت واحد</th>
|
||||
<th>جمع</th>
|
||||
<th>تخفیف محصول</th>
|
||||
<th>تخفیف ویژه</th>
|
||||
<th>قیمت نهایی</th>
|
||||
@@ -277,6 +278,7 @@
|
||||
<td>{{ item_data.item.product.product.name }}</td>
|
||||
<td>{{ item_data.item.product.title }}</td>
|
||||
<td>{{ item_data.item.quantity }}</td>
|
||||
<td>{{ item_data.unit_price|price_format }} تومان</td>
|
||||
<td>{{ item_data.price_before_discount|price_format }} تومان</td>
|
||||
<td class="discount-highlight">
|
||||
{% if item_data.item.discount_percent > 0 %}
|
||||
@@ -292,7 +294,7 @@
|
||||
---
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ item_data.item.price|price_format }} تومان</td>
|
||||
<td>{{ item_data.final_price|price_format }} تومان</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
@@ -304,28 +306,52 @@
|
||||
<span class="summary-label">تعداد کل اقلام:</span>
|
||||
<span class="summary-value">{{ total_items }}</span>
|
||||
</div>
|
||||
<div class="summary-row">
|
||||
<span class="summary-label">جمع کل:</span>
|
||||
|
||||
<!-- 1. Total Before Any Discount -->
|
||||
<div class="summary-row" style="background-color: #e8f5e9; font-weight: bold;">
|
||||
<span class="summary-label">۱. جمع سبد خرید (بعد از تخفیف محصولات):</span>
|
||||
<span class="summary-value">{{ subtotal|price_format }} تومان</span>
|
||||
</div>
|
||||
|
||||
<!-- 2. Product Discount -->
|
||||
<div class="summary-row" style="background-color: #fff3e0;">
|
||||
<span class="summary-label discount-highlight">۲. تخفیف محصولات:</span>
|
||||
<span class="summary-value discount-highlight">
|
||||
{% if items_discount_amount > 0 %}
|
||||
-{{ items_discount_amount|price_format }} تومان
|
||||
{% else %}
|
||||
0 تومان
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- 3. Special Product Discount -->
|
||||
<div class="summary-row" style="background-color: #fce4ec;">
|
||||
<span class="summary-label discount-highlight">۳. تخفیف ویژه محصولات:</span>
|
||||
<span class="summary-value discount-highlight">
|
||||
{% if special_discount_total > 0 %}
|
||||
-{{ special_discount_total|price_format }} تومان
|
||||
{% else %}
|
||||
0 تومان
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{% if discount_amount > 0 %}
|
||||
<div class="summary-row">
|
||||
<span class="summary-label discount-highlight">تخفیف کد:</span>
|
||||
<span class="summary-value discount-highlight">{{ discount_amount|price_format }} تومان</span>
|
||||
<span class="summary-label discount-highlight">تخفیف کد تخفیف:</span>
|
||||
<span class="summary-value discount-highlight">-{{ discount_amount|price_format }} تومان</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if special_discount_total > 0 %}
|
||||
|
||||
<div class="summary-row">
|
||||
<span class="summary-label discount-highlight">تخفیف ویژه:</span>
|
||||
<span class="summary-value discount-highlight">{{ special_discount_total|price_format }} تومان</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="summary-row">
|
||||
<span class="summary-label">مالیات:</span>
|
||||
<span class="summary-label">مالیات ({{ tax_rate }}%):</span>
|
||||
<span class="summary-value">{{ tax|price_format }} تومان</span>
|
||||
</div>
|
||||
|
||||
<!-- 4. Final Price -->
|
||||
<div class="summary-row total">
|
||||
<span class="summary-label">مبلغ قابل پرداخت:</span>
|
||||
<span class="summary-label">۴. قیمت نهایی (قابل پرداخت):</span>
|
||||
<span class="summary-value">{{ final_price|price_format }} تومان</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user