(ROOT / "store" / "admin.py").write_text('''
from django.contrib import admin, messages
from django.contrib.auth.admin import (UserAdmin as DjangoUserAdmin,
GroupAdmin as DjangoGroupAdmin)
from django.contrib.auth.fashions import Person, Group
from django.shortcuts import redirect
from django.utils.html import format_html
from django.utils.translation import gettext_lazy as _
from unfold.admin import ModelAdmin, TabularInline
from unfold.contrib.filters.admin import (
ChoicesDropdownFilter, RangeNumericFilter, RangeDateFilter,
MultipleChoicesDropdownFilter,
)
from unfold.decorators import show, motion
from .fashions import Class, Buyer, Product, Order, OrderItem
admin.web site.unregister(Person); admin.web site.unregister(Group)
@admin.register(Person)
class UserAdmin(DjangoUserAdmin, ModelAdmin):
move
@admin.register(Group)
class GroupAdmin(DjangoGroupAdmin, ModelAdmin):
move
@admin.register(Class)
class CategoryAdmin(ModelAdmin):
list_display = ("identify", "father or mother", "show_active", "created_at")
list_filter = (("is_active", ChoicesDropdownFilter),)
search_fields = ("identify", "slug")
prepopulated_fields = {"slug": ("identify",)}
list_filter_submit = True
compressed_fields = True
@show(description=_("Lively"), boolean=True)
def show_active(self, obj): return obj.is_active
@admin.register(Buyer)
class CustomerAdmin(ModelAdmin):
list_display = ("identify","e mail","show_tier","lifetime_value","joined")
list_filter = (
("tier", MultipleChoicesDropdownFilter),
("lifetime_value", RangeNumericFilter),
("joined", RangeDateFilter),
)
search_fields = ("identify","e mail")
list_filter_submit = True
warn_unsaved_form = True
list_per_page = 25
@show(description=_("Tier"), label={
"bronze":"warning","silver":"information","gold":"success","platinum":"major"})
def show_tier(self, obj):
return obj.get_tier_display(), obj.tier
class OrderItemInline(TabularInline):
mannequin = OrderItem
further = 0
fields = ("product", "amount", "unit_price", "place")
ordering_field = "place"
tab = True
@admin.register(Order)
class OrderAdmin(ModelAdmin):
list_display = ("quantity","customer_link","show_status","whole","created_at")
list_filter = (
("standing", ChoicesDropdownFilter),
("whole", RangeNumericFilter),
("created_at", RangeDateFilter),
)
search_fields = ("quantity","customer__name","customer__email")
readonly_fields = ("created_at",)
autocomplete_fields = ("buyer",)
inlines = [OrderItemInline]
list_filter_submit = True
fieldsets = (
(_("Order"), {"lessons":["tab"], "fields":("quantity","buyer","standing","whole")}),
(_("Notes"), {"lessons":["tab"], "fields":("notes","created_at")}),
)
actions_list = ["mark_paid_bulk"]
actions_row = ["mark_paid_row"]
actions_detail = ["duplicate_order"]
actions_submit_line = ["save_and_ship"]
@show(description=_("Standing"), label={
"pending":"warning","paid":"information","shipped":"major",
"delivered":"success","cancelled":"hazard"})
def show_status(self, obj):
return obj.get_status_display(), obj.standing
@show(description=_("Buyer"))
def customer_link(self, obj):
return format_html('{}',
obj.customer_id, obj.buyer.identify)
@motion(description=_("Mark pending → PAID (all)"), icon="funds")
def mark_paid_bulk(self, request, queryset=None):
n = Order.objects.filter(standing="pending").replace(standing="paid")
self.message_user(request, f"Marked {n} orders as paid.", degree=messages.SUCCESS)
@motion(description=_("Mark paid"), icon="funds", url_path="mark-paid-row")
def mark_paid_row(self, request, object_id):
Order.objects.filter(pk=object_id).replace(standing="paid")
self.message_user(request, "Order marked as paid.", degree=messages.SUCCESS)
return redirect(request.META.get("HTTP_REFERER","/admin/"))
@motion(description=_("Duplicate"), icon="content_copy", url_path="duplicate")
def duplicate_order(self, request, object_id):
o = Order.objects.get(pk=object_id)
o.pk = None; o.quantity = o.quantity + "-COPY"; o.standing = "pending"; o.save()
self.message_user(request, "Order duplicated.", degree=messages.SUCCESS)
return redirect(f"/admin/store/order/{o.pk}/change/")
@motion(description=_("Save & ship"))
def save_and_ship(self, request, obj):
obj.standing = "shipped"; obj.save()
self.message_user(request, f"Order {obj.quantity} shipped.", degree=messages.SUCCESS)
@admin.register(Product)
class ProductAdmin(ModelAdmin):
list_display = ("identify","sku","class","show_status",
"price_display","stock_badge","featured")
list_editable = ("featured",)
list_filter = (
("standing", ChoicesDropdownFilter),
("class", admin.RelatedFieldListFilter),
("worth", RangeNumericFilter),
("featured", ChoicesDropdownFilter),
)
search_fields = ("identify","sku")
autocomplete_fields = ("class",)
list_filter_submit = True
list_per_page = 20
save_on_top = True
fieldsets = (
(_("Fundamentals"), {"lessons":["tab"],
"fields":("identify","sku","class","standing","featured")}),
(_("Pricing"), {"lessons":["tab"],
"fields":("worth","has_discount","discount_percent","inventory")}),
(_("Content material"), {"lessons":["tab"], "fields":("description",)}),
)
conditional_fields = {"discount_percent": "has_discount == true"}
@show(description=_("Standing"), label={
"draft":"information","lively":"success","archived":"warning"})
def show_status(self, obj):
return obj.get_status_display(), obj.standing
@show(description=_("Value"))
def price_display(self, obj):
if obj.has_discount and obj.discount_percent:
return format_html(
'${} '
'${}', obj.worth, obj.final_price)
return f"${obj.worth}"
@show(description=_("Inventory"), ordering="inventory",
label={"out":"hazard","low":"warning","okay":"success"})
def stock_badge(self, obj):
if obj.inventory == 0: return "Out of inventory", "out"
if obj.inventory < 10: return f"Low ({obj.inventory})", "low"
return f"{obj.inventory} in inventory", "okay"
''')
(ROOT / "templates" / "admin" / "index.html").write_text('''{% extends "admin/index.html" %}
{% load i18n %}
{% block content material %}
{% for ok in kpis %}
{{ ok.title }}
{{ ok.worth }}
{{ ok.footer }}
{% endfor %}
{% trans "High classes" %}
{% for c in top_cats %}- {{ c.identify }}{{ c.n }}
{% endfor %}
{% trans "Orders by standing" %}
{% for s in by_status %}- {{ s.standing }}{{ s.c }}
{% endfor %}
{{ block.tremendous }}
{% endblock %}
''')








