Files
MathApp/payment/tests_invoices.py
Zareian 663252a260 Remove the guest system entirely: no is_guest/device_id, no guest throttles, phone login is the only way in
accounts.0008 drops the columns and refuses to run while guest rows exist.
Docs describe the current state; tests that only proved guest behaviour are gone.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 18:20:10 +03:30

93 lines
4.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
GET /api/payment/invoices — «پرداخت‌ها و فاکتورها»ی پروفایل (۲۰۲۶-۱۰-۰۱).
راه‌های شکستن که این‌جا امتحان می‌شوند: دیدنِ فاکتورِ دیگری، عوض شدنِ فاکتورِ قدیمی
با عوض شدنِ قیمتِ پلن، و نشان دادنِ refِ ساختگیِ کدِ ۱۰۰٪ به‌جای کدِ پیگیریِ بانکی.
"""
from django.core.cache import cache
from django.test import TestCase
from rest_framework.test import APIClient
from accounts.authentication import issue_access_token
from accounts.models import User
from discount.models import DiscountCode
from payment.models import Order
from payment.services import apply_order_payment_result
from subscription.models import Plan
def _client(user):
client = APIClient()
client.credentials(HTTP_AUTHORIZATION=f'Bearer {issue_access_token(user.id)}')
return client
class InvoiceTests(TestCase):
def setUp(self):
cache.clear()
self.user = User.objects.create(phone='09120007001')
self.client = _client(self.user)
self.plan = Plan.objects.create(title='سالانه', price=299000, duration_days=365)
def tearDown(self):
cache.clear()
def buy(self):
response = self.client.post('/api/subscription/purchase', {'planId': str(self.plan.id)}, format='json')
self.assertEqual(response.status_code, 200, response.content)
return Order.objects.get(pk=response.json()['orderId'])
def invoices(self, client=None):
response = (client or self.client).get('/api/payment/invoices')
self.assertEqual(response.status_code, 200, response.content)
return response.json()['invoices']
def test_paid_order_with_discount_reads_like_an_invoice(self):
order = self.buy()
DiscountCode.objects.create(code='MEHR20', type='percent', value=20, max_uses=5)
redeem = self.client.post('/api/discount/redeem', {'code': 'MEHR20', 'orderId': str(order.id)}, format='json')
self.assertEqual(redeem.status_code, 200, redeem.content)
apply_order_payment_result(order=order, gateway='zarinpal', gateway_ref_id='A00000123456',
new_status='paid', event='test')
[invoice] = self.invoices()
self.assertEqual(invoice['invoiceNumber'], f'TD-{order.id:06d}')
self.assertEqual(invoice['status'], 'paid')
self.assertEqual(invoice['planTitle'], 'سالانه')
self.assertEqual((invoice['listPrice'], invoice['discountAmount'], invoice['amount']),
(299000, 59800, 239200))
self.assertEqual(invoice['discountCode'], 'MEHR20')
self.assertEqual(invoice['refId'], 'A00000123456')
self.assertIsNotNone(invoice['paidAt'])
def test_changing_the_plan_later_does_not_rewrite_an_old_invoice(self):
self.buy()
Plan.objects.filter(pk=self.plan.pk).update(title='سالانه‌ی ویژه', price=399000)
[invoice] = self.invoices()
self.assertEqual((invoice['planTitle'], invoice['listPrice']), ('سالانه', 299000))
def test_full_discount_shows_no_fake_bank_reference(self):
order = self.buy()
DiscountCode.objects.create(code='FREE100', type='percent', value=100, max_uses=5)
self.client.post('/api/discount/redeem', {'code': 'FREE100', 'orderId': str(order.id)}, format='json')
[invoice] = self.invoices()
self.assertEqual((invoice['status'], invoice['amount'], invoice['refId']), ('paid', 0, ''))
def test_unpaid_orders_are_listed_too(self):
self.buy()
[invoice] = self.invoices()
self.assertEqual((invoice['status'], invoice['paidAt'], invoice['refId']), ('pending', None, ''))
def test_someone_else_sees_nothing(self):
self.buy()
stranger = User.objects.create(phone='09120007002')
self.assertEqual(self.invoices(_client(stranger)), [])
def test_orders_from_before_the_snapshot_have_no_list_price(self):
Order.objects.create(user_id=self.user.id, amount=99000, idempotency_key='old-order')
[invoice] = self.invoices()
self.assertEqual((invoice['listPrice'], invoice['discountAmount'], invoice['planTitle']), (None, None, ''))
def test_requires_a_token(self):
self.assertIn(APIClient().get('/api/payment/invoices').status_code, (401, 403))