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:
@@ -81,6 +81,9 @@ class LedgerEntrySerializer(serializers.ModelSerializer):
|
||||
category_display = serializers.CharField(source="get_category_display", read_only=True)
|
||||
account_name = serializers.CharField(source="account.name", read_only=True, default="")
|
||||
account_code = serializers.CharField(source="account.code", read_only=True, default="")
|
||||
discount_amount = serializers.FloatField(read_only=True)
|
||||
tax_amount = serializers.FloatField(read_only=True)
|
||||
computed_amount = serializers.FloatField(read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = LedgerEntry
|
||||
@@ -88,6 +91,8 @@ class LedgerEntrySerializer(serializers.ModelSerializer):
|
||||
"id", "entry_type", "title", "amount", "category", "category_display",
|
||||
"entry_date", "note", "total_amount", "counterparty_name", "counterparty_phone",
|
||||
"linked_invoice", "account_name", "account_code",
|
||||
"base_amount", "discount_percent", "tax_percent",
|
||||
"discount_amount", "tax_amount", "computed_amount",
|
||||
"is_debt", "professional_type", "paid_amount", "remaining_amount",
|
||||
"installments", "updated_at",
|
||||
]
|
||||
@@ -112,7 +117,8 @@ class ProductSerializer(serializers.ModelSerializer):
|
||||
fields = [
|
||||
"id", "name", "sku", "category", "unit", "quantity",
|
||||
"unit_price", "purchase_price", "total_purchase_value",
|
||||
"low_stock_threshold", "is_low_stock", "notes", "updated_at",
|
||||
"low_stock_threshold", "is_low_stock", "is_active",
|
||||
"production_date", "expiry_date", "notes", "updated_at",
|
||||
]
|
||||
read_only_fields = ["total_purchase_value", "is_low_stock", "updated_at"]
|
||||
|
||||
@@ -153,7 +159,9 @@ class InvoiceSerializer(serializers.ModelSerializer):
|
||||
"id", "invoice_number", "invoice_date", "customer",
|
||||
"buyer_name", "buyer_phone", "buyer_address",
|
||||
"seller_name", "seller_phone", "seller_address",
|
||||
"total_amount", "discount_amount", "tax_lines", "final_amount",
|
||||
"total_amount", "discount_percent", "discount_amount",
|
||||
"extra_discount_label", "extra_discount_percent", "extra_discount_amount",
|
||||
"tax_lines", "final_amount",
|
||||
"payment_type", "payment_type_display",
|
||||
"payment_status", "payment_status_display",
|
||||
"order_status", "order_status_display",
|
||||
@@ -188,7 +196,17 @@ class CreateInvoiceSerializer(serializers.Serializer):
|
||||
seller_name = serializers.CharField(max_length=150, required=False, allow_blank=True, default="")
|
||||
seller_phone = serializers.CharField(max_length=20, required=False, allow_blank=True, default="")
|
||||
seller_address = serializers.CharField(max_length=255, required=False, allow_blank=True, default="")
|
||||
# درصد اولویت دارد: اگر discount_percent مثبت باشد، discount_amount از
|
||||
# روی همان محاسبه میشود (همالگو با تخفیفِ درصدیِ هر قلم فاکتور)؛
|
||||
# discount_amount خامْ فقط برای سازگاری با کلاینتهای قدیمی نگه داشته
|
||||
# شده — اگر درصد صفر باشد همان مقدار مستقیم استفاده میشود.
|
||||
discount_percent = serializers.FloatField(required=False, default=0, min_value=0, max_value=100)
|
||||
discount_amount = serializers.FloatField(required=False, default=0, min_value=0)
|
||||
# تخفیفِ ویژه/دورهای — جدا از تخفیفِ بالا، روی مبلغِ بعد از آن اعمال
|
||||
# میشود. یا با درصد یا با مبلغِ ثابت پر میشود.
|
||||
extra_discount_label = serializers.CharField(max_length=100, required=False, allow_blank=True, default="")
|
||||
extra_discount_percent = serializers.FloatField(required=False, default=0, min_value=0, max_value=100)
|
||||
extra_discount_amount = serializers.FloatField(required=False, default=0, min_value=0)
|
||||
tax_lines = serializers.ListField(child=serializers.DictField(), required=False, default=list)
|
||||
payment_type = serializers.ChoiceField(choices=Invoice.PaymentType.choices, required=False)
|
||||
shipping_method = serializers.ChoiceField(choices=Invoice.ShippingMethod.choices, required=False)
|
||||
|
||||
Reference in New Issue
Block a user