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>
93 lines
4.3 KiB
Python
93 lines
4.3 KiB
Python
"""
|
||
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))
|