ShopOrderModel and ShopDailyReport system
This commit is contained in:
+109
-2
@@ -1,3 +1,6 @@
|
||||
from .models import ShopOrderModel, ShopOrderItem
|
||||
from django.db import transaction
|
||||
from django.db.models.signals import post_save
|
||||
from django.db.models.signals import pre_save
|
||||
from django.dispatch import receiver
|
||||
from .models import OrderModel
|
||||
@@ -26,17 +29,121 @@ def order_status_changed(sender, instance, **kwargs):
|
||||
@receiver(pre_save, sender=OrderModel)
|
||||
def set_default_address(sender, instance, **kwargs):
|
||||
if instance.address is None and instance.user:
|
||||
default_address = UserAddressModel.objects.filter(user=instance.user, is_main=True).first()
|
||||
default_address = UserAddressModel.objects.filter(
|
||||
user=instance.user, is_main=True).first()
|
||||
if default_address:
|
||||
instance.address = default_address
|
||||
|
||||
|
||||
|
||||
# def update_cart_price_fields(order):
|
||||
# pass
|
||||
|
||||
def update_sell_data(order):
|
||||
pass
|
||||
|
||||
|
||||
def update_quantity(order):
|
||||
pass
|
||||
|
||||
|
||||
@receiver(post_save, sender=OrderModel)
|
||||
def create_shop_orders_on_payment(sender, instance: OrderModel, created, **kwargs):
|
||||
"""When an order becomes paid, split it into per-shop ShopOrderModel records.
|
||||
|
||||
This handler is safe to run multiple times (it checks if shop_orders exist).
|
||||
It triggers only when `is_paid` is True.
|
||||
"""
|
||||
# Only generate when order is paid and we don't already have shop orders
|
||||
if not instance.is_paid:
|
||||
return
|
||||
|
||||
if instance.shop_orders.exists():
|
||||
return
|
||||
|
||||
# Collect order items grouped by shop
|
||||
items = instance.items.select_related('product__product__shop')
|
||||
|
||||
shop_groups = {}
|
||||
for item in items:
|
||||
# product is ProductVariant -> product.product is ProductModel -> shop on ProductModel
|
||||
shop = None
|
||||
try:
|
||||
shop = item.product.product.shop
|
||||
except Exception:
|
||||
shop = None
|
||||
|
||||
if not shop:
|
||||
# If product has no shop, skip (or you might want a default platform shop)
|
||||
continue
|
||||
|
||||
shop_groups.setdefault(shop, []).append(item)
|
||||
|
||||
if not shop_groups:
|
||||
return
|
||||
|
||||
# Totals for proportional distribution
|
||||
shop_subtotals = {}
|
||||
for shop, items_list in shop_groups.items():
|
||||
subtotal = 0
|
||||
for it in items_list:
|
||||
subtotal += int(it.price) * int(it.quantity)
|
||||
shop_subtotals[shop] = subtotal
|
||||
|
||||
total_subtotal = sum(shop_subtotals.values()) or 1
|
||||
|
||||
order_discount = int(instance.discount_amount or 0)
|
||||
order_special_discount = int(instance.special_discount_total or 0)
|
||||
order_tax = int(instance.tax or 0)
|
||||
|
||||
with transaction.atomic():
|
||||
for shop, items_list in shop_groups.items():
|
||||
shop_subtotal = shop_subtotals.get(shop, 0)
|
||||
# proportionally allocate cart-level discount, special discount and tax
|
||||
allocated_discount = int(
|
||||
order_discount * shop_subtotal / total_subtotal) if order_discount else 0
|
||||
allocated_special_discount = int(
|
||||
order_special_discount * shop_subtotal / total_subtotal) if order_special_discount else 0
|
||||
allocated_tax = int(order_tax * shop_subtotal /
|
||||
total_subtotal) if order_tax else 0
|
||||
|
||||
commission_percent = getattr(shop, 'commission_percent', 0) or 0
|
||||
try:
|
||||
commission_percent_value = float(commission_percent)
|
||||
except Exception:
|
||||
commission_percent_value = 0.0
|
||||
|
||||
# commission is calculated on the shop subtotal after discounts
|
||||
base_for_commission = max(
|
||||
0, shop_subtotal - 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
|
||||
|
||||
shop_order = ShopOrderModel.objects.create(
|
||||
order=instance,
|
||||
shop=shop,
|
||||
subtotal=shop_subtotal,
|
||||
items_count=sum(int(it.quantity) for it in items_list),
|
||||
discount_amount=allocated_discount,
|
||||
special_discount_amount=allocated_special_discount,
|
||||
commission_percent=commission_percent_value,
|
||||
commission_amount=commission_amount,
|
||||
tax_amount=allocated_tax,
|
||||
payable_amount=payable,
|
||||
)
|
||||
|
||||
# Create ShopOrderItem rows linking to original OrderItemModel
|
||||
for it in items_list:
|
||||
ShopOrderItem.objects.create(
|
||||
shop_order=shop_order,
|
||||
order_item=it,
|
||||
quantity=int(it.quantity),
|
||||
unit_price=int(it.price),
|
||||
total_price=int(it.price) * int(it.quantity),
|
||||
discount_amount=int(
|
||||
it.price) * int(it.quantity) * (int(it.discount_percent or 0) / 100.0),
|
||||
special_discount_amount=int(
|
||||
it.special_discount_amount or 0),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user