831e656fa3
- 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)
54 lines
2.0 KiB
Python
54 lines
2.0 KiB
Python
from rest_framework import serializers
|
|
|
|
from apps.reviews.models import Review
|
|
|
|
|
|
def _display_name(user) -> str:
|
|
if user.name:
|
|
return user.name
|
|
# حریمِ خصوصی: برای کاربرِ بینام، فقط ۴ رقمِ آخرِ شماره نشان داده میشود.
|
|
return f"کاربر ...{user.phone[-4:]}"
|
|
|
|
|
|
class ReviewSerializer(serializers.ModelSerializer):
|
|
user_display = serializers.SerializerMethodField()
|
|
like_count = serializers.IntegerField(read_only=True)
|
|
liked_by_me = serializers.SerializerMethodField()
|
|
is_mine = serializers.SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = Review
|
|
fields = [
|
|
"id", "user_display", "body", "is_approved",
|
|
"like_count", "liked_by_me", "is_mine", "created_at", "updated_at",
|
|
]
|
|
read_only_fields = ["is_approved", "created_at", "updated_at"]
|
|
|
|
def get_user_display(self, obj: Review) -> str:
|
|
return _display_name(obj.user)
|
|
|
|
def get_liked_by_me(self, obj: Review) -> bool:
|
|
request = self.context.get("request")
|
|
if request is None or not request.user.is_authenticated:
|
|
return False
|
|
# get_liked_ids (اگر در context باشد) از یک کوئریِ batch پر میشود تا
|
|
# برای فهرست، بهازای هر نظر یک کوئریِ جدا نزنیم.
|
|
liked_ids = self.context.get("liked_ids")
|
|
if liked_ids is not None:
|
|
return obj.id in liked_ids
|
|
return obj.likes.filter(user=request.user).exists()
|
|
|
|
def get_is_mine(self, obj: Review) -> bool:
|
|
request = self.context.get("request")
|
|
return bool(request and request.user.is_authenticated and obj.user_id == request.user.id)
|
|
|
|
|
|
class ReviewWriteSerializer(serializers.Serializer):
|
|
body = serializers.CharField(max_length=1000)
|
|
|
|
def validate_body(self, value: str) -> str:
|
|
value = value.strip()
|
|
if not value:
|
|
raise serializers.ValidationError("متنِ نظر نمیتواند خالی باشد.")
|
|
return value
|