feat: add daily report functionality and settlement status to shop orders

This commit is contained in:
Parsa Nazer
2026-02-09 11:08:39 +03:30
parent 0771a286b2
commit bd7c7252c7
6 changed files with 78 additions and 11 deletions
+37 -6
View File
@@ -1,6 +1,7 @@
from django.contrib import admin, messages
from .models import *
from unfold.admin import TabularInline, StackedInline
from unfold.contrib.inlines.admin import NonrelatedTabularInline
from django.db.models import Q
from import_export.admin import ImportExportModelAdmin
from unfold.contrib.import_export.forms import ExportForm, ImportForm, SelectableFieldsExportForm
@@ -60,19 +61,50 @@ class CartAdmin(ModelAdmin):
inlines = [CartItemInline]
class ShopOrderInline(StackedInline):
model = ShopOrderModel
extra = 0
max_num = 0
tab = True
class ShopOrderItemInline(NonrelatedTabularInline): # NonrelatedStackedInline is available as well
model = ShopOrderItem
tab = True
extra = 0
show_change_link = True
def get_form_queryset(self, obj):
"""
Gets all nonrelated objects needed for inlines. Method must be implemented.
"""
shop_orders = obj.shop_orders.all()
return ShopOrderItem.objects.filter(shop_order__in=shop_orders)
def save_new_instance(self, parent, instance):
"""
Extra save method which can for example update inline instances based on current
main model object. Method must be implemented.
"""
pass
from .models import ShopDailyReport, ShopOrderModel
@admin.register(ShopDailyReport)
class ShopDailyReportAdmin(ModelAdmin):
pass
list_display = ['shop', 'date', 'is_settled',]
inlines = [ShopOrderInline, ShopOrderItemInline]
def get_queryset(self, request):
if request.user.is_superuser:
return ShopOrderModel.objects.all()
return self.model.objects.all()
if not hasattr(request.user, 'shop'):
return ShopOrderModel.objects.none()
return self.model.objects.none()
queryset = ShopOrderModel.objects.filter(shop=request.user.shop)
queryset = self.model.objects.filter(shop=request.user.shop)
return queryset
def has_view_permission(self, request, obj=None):
@@ -95,11 +127,10 @@ class ShopOrderItemInline(StackedInline):
@admin.register(ShopOrderModel)
class ShopOrderModelAdmin(ShopOrderAdminPermission, ModelAdmin):
inlines = [ShopOrderItemInline]
list_display = ['id', 'shop', 'order', 'customer_name', 'status', 'is_paid', 'is_settled', 'download_invoice_button']
list_display = ['id', 'shop', 'order', 'customer_name', 'status', 'is_paid', 'is_settled', 'created_at', 'download_invoice_button']
readonly_fields = ['download_invoice_link']
def download_invoice_button(self, obj):
@@ -0,0 +1,24 @@
# Generated by Django 5.1.2 on 2026-02-08 15:40
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('order', '0042_ordermodel_special_discount_code_and_more'),
]
operations = [
migrations.AddField(
model_name='shopdailyreport',
name='is_settled',
field=models.BooleanField(default=False, verbose_name='تسویه شده'),
),
migrations.AddField(
model_name='shopordermodel',
name='daily_report',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='shop_orders', to='order.shopdailyreport', verbose_name='گزارش روزانه'),
),
]
+2
View File
@@ -279,6 +279,7 @@ class ShopOrderModel(models.Model):
"""
order = models.ForeignKey(OrderModel, on_delete=models.CASCADE, related_name='shop_orders')
shop = models.ForeignKey('account.ShopModel', on_delete=models.CASCADE, related_name='shop_orders')
daily_report = models.ForeignKey('ShopDailyReport', on_delete=models.SET_NULL, null=True, blank=True, related_name='shop_orders', verbose_name='گزارش روزانه')
# Customer Information
customer = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, verbose_name='مشتری')
@@ -355,6 +356,7 @@ class ShopDailyReport(models.Model):
total_sales = models.BigIntegerField(default=0)
total_commission = models.BigIntegerField(default=0)
total_payable = models.BigIntegerField(default=0)
is_settled = models.BooleanField(default=False, verbose_name='تسویه شده')
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
+8 -1
View File
@@ -1,4 +1,4 @@
from .models import ShopOrderModel, ShopOrderItem
from .models import ShopOrderModel, ShopOrderItem, ShopDailyReport
from django.db import transaction
from django.db.models.signals import post_save
from django.db.models.signals import pre_save
@@ -249,3 +249,10 @@ def send_invoice_to_shop_telegram(sender, instance: ShopOrderModel, created, **k
chat_id=instance.shop.telegram_chat_id,
bot_token=bot_token
)
@receiver(post_save, sender=ShopDailyReport)
def update_shop_orders_settlement_status(sender, instance: ShopDailyReport, **kwargs):
"""When a ShopDailyReport's is_settled status changes, update all related ShopOrderModel instances."""
# Update all shop orders linked to this daily report
instance.shop_orders.update(is_settled=instance.is_settled)
+4 -1
View File
@@ -77,7 +77,7 @@ def generate_daily_shop_reports():
from .models import ShopOrderModel, ShopDailyReport
target_date = (timezone.now() - timedelta(days=1)).date()
logging.info(f'Generating shop reports for {target_date}')
print(f'Generating shop reports for {target_date}')
shop_orders = ShopOrderModel.objects.filter(created_at__date=target_date)
if not shop_orders.exists():
@@ -110,6 +110,9 @@ def generate_daily_shop_reports():
}
)
# Link all shop orders for this shop and date to the daily report
shop_orders.filter(shop_id=shop_id).update(daily_report=report)
if created:
reports_created += 1
else:
+1 -1
View File
@@ -42,7 +42,7 @@ django-iranian-cities==1.0.2
django-jalali==7.3.0
django-storages==1.14.5
django-timezone-field==7.1
django-unfold==0.48.0
django-unfold==0.78.1
djangorestframework==3.15.2
djangorestframework-simplejwt==5.3.1
djoser==2.3.1