from utils.admin_base import CRMModelAdmin from utils.admin_excel import excel_response from apps.shop.admin_import import ProductImportAdminMixin from apps.shop.import_models import ProductImportBatch from django.contrib import admin from django.urls import reverse from django.utils.html import format_html from apps.shop.models import ProductCategory, Product, Order, OrderItem, Cart, ProductType from apps.shop.ordering import category_ordering, product_ordering def export_products(queryset): headers = ('فضای کاری', 'دسته', 'محصول', 'کد محصول', 'قیمت', 'ترتیب نمایش دسته', 'ترتیب نمایش محصول', 'ترتیب اکسل دسته', 'ترتیب اکسل محصول', 'فقط نمایش', 'ویژگی‌ها') categories = {category.pk: (category.name, category.parent_id) for category in ProductCategory.objects.filter(sys_ws_id__in=queryset.values('sys_ws_id'))} def path(category_id): names, visited = [], set() while category_id in categories and category_id not in visited: visited.add(category_id) name, category_id = categories[category_id] names.append(name) return '/'.join(reversed(names)) rows = ((item.sys_ws.name, path(item.category_id), item.name, item.acc_code, item.price, item.category.order_cat, item.order_prd, item.category.excel_order, item.excel_order, item.view_only, item.attr) for item in queryset.select_related('sys_ws', 'category').iterator()) return excel_response(headers, rows, 'products.xlsx') class ProductInline(admin.TabularInline): model = Product fields = ('name', 'price', 'order_prd', 'excel_order') extra = 0 show_change_link = True readonly_fields = ('name', 'price') can_delete = False def has_add_permission(self, request, obj=None): return False @admin.register(ProductType) class ProductTypeAdmin(CRMModelAdmin): pass @admin.register(ProductCategory) class ProductCategoryAdmin(CRMModelAdmin): list_display = ('name', 'sys_ws', 'parent', 'order_cat', 'excel_order') list_editable = ('order_cat', 'excel_order') list_filter = ('sys_ws',) search_fields = ('name',) inlines = (ProductInline,) actions = ('export_display_order', 'export_excel_order') @admin.action(description='خروجی اکسل دسته‌ها با ترتیب نمایش فعلی') def export_display_order(self, request, queryset): return self.export_categories(queryset) @admin.action(description='خروجی اکسل دسته‌ها با ترتیب مستقل اکسل') def export_excel_order(self, request, queryset): return self.export_categories(queryset.order_by(*category_ordering(excel=True))) def export_categories(self, queryset): return excel_response(('فضای کاری', 'دسته', 'ترتیب نمایش', 'ترتیب اکسل'), queryset.values_list('sys_ws__name', 'name', 'order_cat', 'excel_order'), 'categories.xlsx') @admin.register(Product) class ProductAdmin(ProductImportAdminMixin, CRMModelAdmin): list_display = ('name', 'category', 'sys_ws', 'price', 'order_prd', 'excel_order', 'view_only') list_editable = ('order_prd', 'excel_order') list_filter = ('sys_ws', 'category', 'view_only') search_fields = ('name', 'category__name', 'acc_code') list_select_related = ('category', 'sys_ws') actions = ('export_display_order', 'export_excel_order') @admin.action(description='خروجی اکسل محصولات با ترتیب نمایش فعلی') def export_display_order(self, request, queryset): return export_products(queryset) @admin.action(description='خروجی اکسل محصولات با ترتیب مستقل اکسل') def export_excel_order(self, request, queryset): return export_products(queryset.order_by(*product_ordering(excel=True))) @admin.register(Order) class OrderAdmin(CRMModelAdmin): list_display = ('id', 'customer', 'sys_ws', 'total_price', 'factor_type', 'factor_status', 'view_at', 'created_at') @admin.register(OrderItem) class OrderItemAdmin(CRMModelAdmin): list_display = ('id', 'order', 'product', 'product_name', 'price', 'amount') search_fields = ('product_name', 'product__name', 'order__customer__name_family') @admin.register(Cart) class CartAdmin(CRMModelAdmin): list_display = ('id', 'cuser_role', 'product', 'quantity', 'sys_ws', 'updated_at') @admin.register(ProductImportBatch) class ProductImportBatchAdmin(CRMModelAdmin): list_display = ("id", "filename", "sys_ws", "created_by", "summary", "created_at", "confirmed_at") search_fields = ("filename", "created_by__username") exclude = ("payload", "fingerprint", "result") sensitive_fields = ("payload", "fingerprint", "result") actions = None def get_readonly_fields(self, request, obj=None): fields = tuple(field.name for field in self.model._meta.fields if field.name not in self.exclude) return (*fields, 'summary', 'report_link') if obj and obj.created_by_id == request.user.pk else (*fields, 'summary') @admin.display(description='خلاصه نتیجه') def summary(self, obj): result = obj.result status = 'ثبت نهایی' if obj.confirmed_at else 'پیش‌نمایش' return f"{status} | ایجاد: {result.get('created', 0)} | به‌روزرسانی: {result.get('updated', 0)} | خطا: {result.get('errors', 0)}" @admin.display(description='گزارش ردیف‌ها') def report_link(self, obj): return format_html('دریافت اکسل گزارش', reverse('admin:shop_product_import_report', args=[obj.pk])) def has_add_permission(self, request): return False def has_change_permission(self, request, obj=None): return False def has_delete_permission(self, request, obj=None): return False