try fix of creating shop order model

This commit is contained in:
Parsa Nazer
2026-01-04 19:01:38 +03:30
parent e8a64df3de
commit 01eb4754a6
2 changed files with 59 additions and 28 deletions
+46 -24
View File
@@ -99,35 +99,57 @@ 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
# Prepare items with calculated discount amounts using stored values
items = shop_order.items.select_related('order_item').all()
total_before_any_discount = 0
total_product_discount = 0
items_with_discount = []
total_items_discount = 0
total_special_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
# Calculate discount amount based on stored values
# discount_amount = shop_item.discount_amount or 0
# special_discount_amount = shop_item.special_discount_amount or 0
total_items_discount += shop_item.discount_amount or 0
total_special_discount += shop_item.special_discount_amount or 0
# # Calculate unit price (after product discount, before special discount)
# unit_price = shop_item.unit_price or 0
# # Calculate price before discount (original unit price)
# if order_item.discount_percent > 0:
# discount_multiplier = (100 - order_item.discount_percent) / 100
# if discount_multiplier > 0:
# price_before_discount_unit = int(unit_price / discount_multiplier)
# else:
# price_before_discount_unit = unit_price
# else:
# price_before_discount_unit = unit_price
# price_before_discount = price_before_discount_unit * shop_item.quantity
# # Final price after all discounts
# final_price = shop_item.total_price or 0
items_with_discount.append({
'item': shop_item,
'order_item': order_item,
'discount_amount': order_item.total_product_discount_amount() or 0,
'special_discount_amount': order_item.special_discount_amount or 0,
'price_before_discount': order_item.total_price_before_discount(),
'unit_price': order_item.unit_price or 0,
'final_price': order_item.price_after_special_discount() or 0,
})
# Calculate subtotal (cart total before discounts)
subtotal = shop_order.subtotal or 0
# 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,
'order_number': shop_order.order.pk,
'shop_order_id': shop_order.pk,
'shop': shop_order.shop,
'customer': shop_order.customer,
@@ -140,12 +162,12 @@ def generate_shop_order_invoice(shop_order_id):
'address_province': shop_order.address_province,
'address_recipient_name': shop_order.address_recipient_name,
'items': items,
'items_with_discount': items_with_discount,
'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': 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,
'subtotal': subtotal, # Total after product discount
'items_discount_amount': total_items_discount, # Product discount amount
'special_discount_total': total_special_discount, # Special discount total
'tax_amount': shop_order.tax_amount,
'commission_percent': shop_order.commission_percent,
'commission_amount': shop_order.commission_amount,
+13 -4
View File
@@ -99,6 +99,13 @@ def create_shop_orders_on_payment(sender, instance: OrderModel, created, **kwarg
with transaction.atomic():
for shop, items_list in shop_groups.items():
shop_subtotal = shop_subtotals.get(shop, 0)
# Calculate total item-level discounts for this shop
item_level_discounts = 0
for it in items_list:
item_discount = int(it.price) * int(it.quantity) * (int(it.discount_percent or 0) / 100.0)
item_level_discounts += int(item_discount)
# proportionally allocate cart-level discount, special discount and tax
allocated_discount = int(
order_discount * shop_subtotal / total_subtotal) if order_discount else 0
@@ -113,14 +120,16 @@ def create_shop_orders_on_payment(sender, instance: OrderModel, created, **kwarg
except Exception:
commission_percent_value = 0.0
# commission is calculated on the shop subtotal after discounts
# commission is calculated on the subtotal after ALL discounts (item-level, cart-level, and special)
# but BEFORE tax
base_for_commission = max(
0, shop_subtotal - allocated_discount - allocated_special_discount)
0, shop_subtotal - item_level_discounts - allocated_discount - allocated_special_discount)
commission_amount = int(
base_for_commission * (commission_percent_value / 100.0))
payable = shop_subtotal - allocated_discount - \
allocated_special_discount - commission_amount + allocated_tax
# Payable to shop: subtotal minus all discounts minus commission (no tax added to payable)
payable = shop_subtotal - item_level_discounts - allocated_discount - \
allocated_special_discount - commission_amount
# Prepare customer information
customer_phone = (instance.user.phone or '') if instance.user else ''