From 01eb4754a645912c8f68cf33ce0083a62bb5cdd1 Mon Sep 17 00:00:00 2001 From: Parsa Nazer Date: Sun, 4 Jan 2026 19:01:38 +0330 Subject: [PATCH] try fix of creating shop order model --- backend/order/invoice_generator.py | 70 ++++++++++++++++++++---------- backend/order/signals.py | 17 ++++++-- 2 files changed, 59 insertions(+), 28 deletions(-) diff --git a/backend/order/invoice_generator.py b/backend/order/invoice_generator.py index d71cce9..26496c1 100644 --- a/backend/order/invoice_generator.py +++ b/backend/order/invoice_generator.py @@ -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, diff --git a/backend/order/signals.py b/backend/order/signals.py index db3e3bc..2f46ac5 100644 --- a/backend/order/signals.py +++ b/backend/order/signals.py @@ -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 ''