admin: cancel a pending order, refund a paid one

There was no way to take an order back: staff could only edit the
status by hand, and turning 'paid' into 'failed' left the credits,
heart days or subscription days the order had given. Two OrderAdmin
actions now do it:
- cancel a pending order (a payment that does arrive later still counts);
- refund a paid order, after a confirmation page: takes back the pack's
  unspent credits (never below zero), its heart days, or the plan's
  subscription days, and undoes the referrer's commission.
The money itself is returned in the Zarinpal / Bazaar panel; the action
says so. Status is read-only in the order form. Steps in
docs/operations.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-02 22:37:30 +03:30
parent 4700ccbf91
commit d7d168e82f
10 changed files with 401 additions and 4 deletions

View File

@@ -0,0 +1,25 @@
{% extends "admin/base_site.html" %}
{% comment %}صفحه‌ی تأییدِ بازپرداخت (payment/admin.py → OrderAdmin.refund). بی‌این صفحه یک کلیکِ اشتباه اعتبارِ کاربر را پس می‌گرفت.{% endcomment %}
{% block content %}
<div dir="rtl" style="max-width:720px">
<h1>بازپرداختِ {{ orders|length }} سفارش</h1>
<p><b>این کار پول را برنمی‌گرداند.</b> پول را جدا از پنلِ زرین‌پال (یا کافه‌بازار) برگردانید. این‌جا فقط چیزی که
سفارش داده بود پس گرفته می‌شود: اعتبارِ خرج‌نشده‌ی بسته، روزهای قلبِ نامحدود، یا روزهای اشتراک.</p>
<table>
<thead><tr><th>سفارش</th><th>کاربر</th><th>پلن</th><th>مبلغ</th><th>درگاه</th><th>تاریخ</th></tr></thead>
<tbody>
{% for o in orders %}
<tr><td>{{ o.id }}</td><td>{{ o.user_id }}</td><td>{{ o.plan_title|default:"—" }}</td>
<td>{{ o.amount }} {{ o.currency }}</td><td>{{ o.get_provider_display }}</td><td>{{ o.created_at|date:"Y-m-d H:i" }}</td></tr>
{% endfor %}
</tbody>
</table>
<form method="post" style="margin-top:16px">{% csrf_token %}
{% for o in orders %}<input type="hidden" name="_selected_action" value="{{ o.pk }}">{% endfor %}
<input type="hidden" name="action" value="refund">
<input type="hidden" name="confirm" value="yes">
<input type="submit" value="بله، بازپرداخت ثبت شود" class="default" style="background:#ba2121">
<a href="" class="button cancel-link" style="margin-right:8px">انصراف</a>
</form>
</div>
{% endblock %}