Fix OTP/SMS, ledger accounting, order tracking, and add reviews app
- Add MessageTemplate.runtime_field_labels so mobile's per-field execution-time labels are actually persisted (were silently dropped) - Fix AdvanceOrderStageView reading the wrong extra-input key, and be honest about SMS send failures instead of always claiming success - Add admin gift-gem SMS notification via Kavenegar - Post real double-entry Transactions for plain (non-invoice) ledger entries so trial balance, the معین screen, and CSV/XLSX exports actually include everyday income/expense entries; backfill existing historical entries via data migration - Rewrite CSV ledger export to produce an actual دفتر معین structure (per-account running balance) instead of a flat row dump - Add invoice percent/promotional discounts, tax presets, ledger discount-percent handling, product SKU/category/expiry fields, and manual ledger-book archiving (replacing auto-archive on new book) - Add reviews app (models, API, admin) for the comments/reviews feature - Update tests for the above; fix two stale assertions left over from earlier work in this branch (معین sheet name, book auto-close)
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
from django.contrib import admin
|
||||
from django.db.models import Count
|
||||
|
||||
from .models import Review, ReviewLike
|
||||
|
||||
|
||||
class ReviewLikeInline(admin.TabularInline):
|
||||
model = ReviewLike
|
||||
extra = 0
|
||||
readonly_fields = ("user", "created_at")
|
||||
can_delete = False
|
||||
|
||||
def has_add_permission(self, request, obj=None):
|
||||
return False
|
||||
|
||||
|
||||
@admin.register(Review)
|
||||
class ReviewAdmin(admin.ModelAdmin):
|
||||
list_display = ("user", "body_preview", "like_count", "is_approved", "created_at")
|
||||
list_filter = ("is_approved", "created_at")
|
||||
list_editable = ("is_approved",)
|
||||
search_fields = ("user__phone", "user__name", "body")
|
||||
readonly_fields = ("user", "created_at", "updated_at")
|
||||
inlines = [ReviewLikeInline]
|
||||
actions = ["approve_reviews", "reject_reviews"]
|
||||
|
||||
def get_queryset(self, request):
|
||||
return super().get_queryset(request).annotate(_like_count=Count("likes"))
|
||||
|
||||
@admin.display(description="متن نظر")
|
||||
def body_preview(self, obj: Review) -> str:
|
||||
return obj.body if len(obj.body) <= 60 else f"{obj.body[:60]}…"
|
||||
|
||||
@admin.display(description="تعداد لایک", ordering="_like_count")
|
||||
def like_count(self, obj: Review) -> int:
|
||||
return obj._like_count
|
||||
|
||||
@admin.action(description="تاییدِ نظرهای انتخابشده")
|
||||
def approve_reviews(self, request, queryset):
|
||||
updated = queryset.update(is_approved=True)
|
||||
self.message_user(request, f"{updated} نظر تایید شد.")
|
||||
|
||||
@admin.action(description="رد کردنِ نظرهای انتخابشده")
|
||||
def reject_reviews(self, request, queryset):
|
||||
updated = queryset.update(is_approved=False)
|
||||
self.message_user(request, f"{updated} نظر رد شد.")
|
||||
Reference in New Issue
Block a user