from decimal import Decimal from django.test import TestCase from django.contrib.auth import get_user_model from rest_framework.test import APIClient from rest_framework import status from apps.profiles.models import Institution from apps.donations.models import DonationCampaign, DonationTransaction, CampaignCategory, CampaignPriority, PaymentStatus User = get_user_model() class Phase9DonationsAPITests(TestCase): """ Automated test suite for Phase 9: Donations & Financial Campaigns - Campaign Listing & Filtering - Campaign Detail & Progress Calculation - Charitable Contribution Flow & Automatic Balance Increment """ def setUp(self): self.client = APIClient() self.donor = User.objects.create_user( email="donor@charitynet.org", password="Password123!", fullname="Haj Ahmad Karimi", ) self.institution = Institution.objects.create( name="Imam Reza Humanitarian Center", country="Afghanistan", city="Herat", type=Institution.InstitutionType.CHARITY, ) self.campaign = DonationCampaign.objects.create( title="Clean Water Wells & Winter Food Baskets for Displaced Families", description="Emergency humanitarian appeal to construct 15 solar-powered clean water wells.", target_amount=Decimal('50000.00'), raised_amount=Decimal('12500.00'), currency='USD', category=CampaignCategory.HUMANITARIAN_RELIEF, priority=CampaignPriority.URGENT, institution=self.institution, organization_name="Astan Relief Foundation", is_active=True, is_featured=True, ) def test_campaign_listing_and_filtering(self): # 1. List response = self.client.get("/api/v1/donations/campaigns/") self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.data), 1) self.assertEqual(response.data[0]["title"], self.campaign.title) self.assertEqual(response.data[0]["progress_percentage"], 25) # 2. Filter by category res_cat = self.client.get(f"/api/v1/donations/campaigns/?category={CampaignCategory.HUMANITARIAN_RELIEF}") self.assertEqual(res_cat.status_code, status.HTTP_200_OK) self.assertEqual(len(res_cat.data), 1) def test_campaign_detail_view(self): response = self.client.get(f"/api/v1/donations/campaigns/{self.campaign.slug}/") self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data["id"], self.campaign.id) self.assertEqual(response.data["target_amount"], "50000.00") self.assertEqual(response.data["progress_percentage"], 25) def test_donation_contribution_flow(self): self.client.force_authenticate(user=self.donor) payload = { "amount": 2500.00, "donor_name": "Haj Ahmad Karimi", } response = self.client.post(f"/api/v1/donations/campaigns/{self.campaign.slug}/contribute/", payload, format="json") self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertTrue(response.data["transaction_reference"].startswith("DON-RAZAVI-")) self.assertEqual(response.data["amount"], "2500.00") self.assertEqual(response.data["payment_status"], PaymentStatus.COMPLETED) # Check campaign raised amount incremented: 12500 + 2500 = 15000 self.campaign.refresh_from_db() self.assertEqual(self.campaign.raised_amount, Decimal('15000.00')) self.assertEqual(self.campaign.progress_percentage, 30) self.assertEqual(self.campaign.donors_count, 1)