Spaces:
Runtime error
Runtime error
| """ | |
| Comprehensive Test Suite for Mirchi Trading Backend | |
| Tests all scenarios: | |
| - Awaak regular transactions | |
| - Jawaak regular transactions | |
| - Patti Awaak (no lot/weight) | |
| - Patti Jawaak (with lot/weight - mandatory) | |
| - Mixed bills (normal + patti items) | |
| - Payments | |
| - Reverts | |
| - Party rename with historical tracking | |
| - Multilingual (Marathi, Hindi, English) inputs | |
| """ | |
| import pytest | |
| import asyncio | |
| from httpx import AsyncClient, ASGITransport | |
| from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker | |
| from sqlalchemy import select | |
| from datetime import datetime | |
| import sys | |
| import os | |
| # Add backend to path | |
| sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | |
| from app.main import app | |
| from app.core.database import Base, get_db | |
| from app.models import Party, MirchiType, Transaction, PattiTransaction, BillNumberSequence | |
| from app.models.transaction import BillType | |
| from app.models.patti_transaction import PattiBillType | |
| from app.models.party import PartyType | |
| # Test database URL (use SQLite for tests) | |
| TEST_DATABASE_URL = "sqlite+aiosqlite:///:memory:" | |
| def event_loop(): | |
| """Create event loop for async tests""" | |
| loop = asyncio.get_event_loop_policy().new_event_loop() | |
| yield loop | |
| loop.close() | |
| async def db_session(): | |
| """Create database session for tests""" | |
| engine = create_async_engine(TEST_DATABASE_URL, echo=False) | |
| async with engine.begin() as conn: | |
| await conn.run_sync(Base.metadata.create_all) | |
| async_session = async_sessionmaker(engine, expire_on_commit=False) | |
| async with async_session() as session: | |
| yield session | |
| await engine.dispose() | |
| async def client(db_session): | |
| """Create test client""" | |
| async def override_get_db(): | |
| yield db_session | |
| app.dependency_overrides[get_db] = override_get_db | |
| async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as ac: | |
| yield ac | |
| app.dependency_overrides.clear() | |
| # ============================================ | |
| # PARTY TESTS | |
| # ============================================ | |
| class TestParty: | |
| """Tests for party operations""" | |
| async def test_create_party_english(self, client: AsyncClient): | |
| """Test creating party with English name""" | |
| response = await client.post("/api/parties", json={ | |
| "name": "Ramesh Kumar", | |
| "phone": "9876543210", | |
| "city": "Mumbai", | |
| "party_type": "awaak", | |
| "notes": "Regular customer" | |
| }) | |
| assert response.status_code == 201 | |
| data = response.json() | |
| assert data["success"] is True | |
| assert data["data"]["name"] == "Ramesh Kumar" | |
| assert data["data"]["party_type"] == "awaak" | |
| async def test_create_party_marathi(self, client: AsyncClient): | |
| """Test creating party with Marathi name""" | |
| response = await client.post("/api/parties", json={ | |
| "name": "रमेश कुमार", | |
| "phone": "9876543210", | |
| "city": "मुंबई", | |
| "party_type": "jawaak", | |
| "notes": "नियमित ग्राहक" | |
| }) | |
| assert response.status_code == 201 | |
| data = response.json() | |
| assert data["data"]["name"] == "रमेश कुमार" | |
| assert data["data"]["city"] == "मुंबई" | |
| async def test_create_party_hindi(self, client: AsyncClient): | |
| """Test creating party with Hindi name""" | |
| response = await client.post("/api/parties", json={ | |
| "name": "राम लाल", | |
| "phone": "9876543211", | |
| "city": "दिल्ली", | |
| "party_type": "both", | |
| "notes": "Hindi customer" | |
| }) | |
| assert response.status_code == 201 | |
| data = response.json() | |
| assert data["data"]["name"] == "राम लाल" | |
| async def test_rename_party(self, client: AsyncClient): | |
| """Test renaming party - should track history""" | |
| # Create party | |
| create_response = await client.post("/api/parties", json={ | |
| "name": "Old Name", | |
| "phone": "9876543212", | |
| "city": "Pune", | |
| "party_type": "awaak" | |
| }) | |
| party_id = create_response.json()["data"]["id"] | |
| # Rename party | |
| rename_response = await client.put(f"/api/parties/{party_id}", json={ | |
| "name": "New Name" | |
| }) | |
| assert rename_response.status_code == 200 | |
| data = rename_response.json() | |
| assert data["data"]["name"] == "New Name" | |
| # Check name history | |
| history_response = await client.get(f"/api/parties/{party_id}/name-history") | |
| assert history_response.status_code == 200 | |
| history = history_response.json() | |
| assert history["current_name"] == "New Name" | |
| assert len(history["name_history"]) == 1 | |
| assert history["name_history"][0]["old_name"] == "Old Name" | |
| assert history["name_history"][0]["new_name"] == "New Name" | |
| # ============================================ | |
| # BILL NUMBER TESTS | |
| # ============================================ | |
| class TestBillNumbering: | |
| """Tests for bill numbering system""" | |
| async def test_get_next_bill_number_awaak(self, client: AsyncClient): | |
| """Test getting next bill number for awaak""" | |
| response = await client.get("/api/transactions/next-bill-number?bill_type=awaak") | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert data["success"] is True | |
| # Format: A2025A001 | |
| assert data["bill_number"].startswith("A") | |
| assert "A" in data["bill_number"] # Batch A | |
| async def test_get_next_bill_number_jawaak(self, client: AsyncClient): | |
| """Test getting next bill number for jawaak""" | |
| response = await client.get("/api/transactions/next-bill-number?bill_type=jawaak") | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert data["bill_number"].startswith("J") | |
| async def test_get_next_bill_number_patti_awaak(self, client: AsyncClient): | |
| """Test getting next bill number for patti_awaak""" | |
| response = await client.get("/api/patti-transactions/next-bill-number?bill_type=patti_awaak") | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert data["bill_number"].startswith("PA") | |
| async def test_get_next_bill_number_patti_jawaak(self, client: AsyncClient): | |
| """Test getting next bill number for patti_jawaak""" | |
| response = await client.get("/api/patti-transactions/next-bill-number?bill_type=patti_jawaak") | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert data["bill_number"].startswith("PJ") | |
| async def test_bill_number_info(self, client: AsyncClient): | |
| """Test getting bill number sequence info""" | |
| response = await client.get("/api/transactions/bill-number-info?bill_type=awaak") | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert "bill_type" in data | |
| assert "year" in data | |
| assert "prefix" in data | |
| assert "batches" in data | |
| assert "total_used" in data | |
| assert "total_remaining" in data | |
| # ============================================ | |
| # TRANSACTION TESTS | |
| # ============================================ | |
| class TestTransactions: | |
| """Tests for regular transactions""" | |
| async def test_create_awaak_transaction(self, client: AsyncClient): | |
| """Test creating awaak (purchase) transaction""" | |
| # Create party first | |
| party_response = await client.post("/api/parties", json={ | |
| "name": "Test Party", | |
| "phone": "9876543213", | |
| "city": "Nagpur", | |
| "party_type": "awaak" | |
| }) | |
| party_id = party_response.json()["data"]["id"] | |
| # Create transaction | |
| response = await client.post("/api/transactions", json={ | |
| "bill_date": datetime.now().strftime("%Y-%m-%d"), | |
| "bill_type": "awaak", | |
| "party_id": party_id, | |
| "subtotal": 10000, | |
| "total_amount": 10500, | |
| "paid_amount": 5000, | |
| "balance_amount": 5500, | |
| "lot_number": "LOT001", | |
| "items": [ | |
| { | |
| "mirchi_name": "Byadgi", | |
| "poti_count": 10, | |
| "net_weight": 500, | |
| "rate_per_kg": 20, | |
| "amount": 10000, | |
| "source": "normal" | |
| } | |
| ], | |
| "payments": [ | |
| { | |
| "amount": 5000, | |
| "mode": "cash", | |
| "reference": "Payment 1" | |
| } | |
| ] | |
| }) | |
| assert response.status_code == 201 | |
| data = response.json() | |
| assert data["success"] is True | |
| assert data["data"]["bill_type"] == "awaak" | |
| assert data["data"]["bill_number"].startswith("A") | |
| assert data["data"]["party_name"] == "Test Party" | |
| assert data["data"]["party_name_current"] == "Test Party" | |
| async def test_create_jawaak_transaction(self, client: AsyncClient): | |
| """Test creating jawaak (sales) transaction""" | |
| # Create party first | |
| party_response = await client.post("/api/parties", json={ | |
| "name": "Sales Party", | |
| "phone": "9876543214", | |
| "city": "Solapur", | |
| "party_type": "jawaak" | |
| }) | |
| party_id = party_response.json()["data"]["id"] | |
| # Create transaction | |
| response = await client.post("/api/transactions", json={ | |
| "bill_date": datetime.now().strftime("%Y-%m-%d"), | |
| "bill_type": "jawaak", | |
| "party_id": party_id, | |
| "subtotal": 15000, | |
| "total_amount": 15500, | |
| "paid_amount": 15500, | |
| "balance_amount": 0, | |
| "items": [ | |
| { | |
| "mirchi_name": "Sankeshwari", | |
| "poti_count": 15, | |
| "net_weight": 750, | |
| "rate_per_kg": 20, | |
| "amount": 15000, | |
| "source": "normal" | |
| } | |
| ], | |
| "payments": [ | |
| { | |
| "amount": 15500, | |
| "mode": "upi", | |
| "reference": "UPI123" | |
| } | |
| ] | |
| }) | |
| assert response.status_code == 201 | |
| data = response.json() | |
| assert data["data"]["bill_type"] == "jawaak" | |
| assert data["data"]["bill_number"].startswith("J") | |
| async def test_create_mixed_bill(self, client: AsyncClient): | |
| """Test creating mixed bill (normal + patti items)""" | |
| # Create party | |
| party_response = await client.post("/api/parties", json={ | |
| "name": "Mixed Party", | |
| "phone": "9876543215", | |
| "city": "Kolhapur", | |
| "party_type": "both" | |
| }) | |
| party_id = party_response.json()["data"]["id"] | |
| # Create mixed transaction | |
| response = await client.post("/api/transactions", json={ | |
| "bill_date": datetime.now().strftime("%Y-%m-%d"), | |
| "bill_type": "awaak", | |
| "party_id": party_id, | |
| "subtotal": 20000, | |
| "total_amount": 20500, | |
| "paid_amount": 10000, | |
| "balance_amount": 10500, | |
| "items": [ | |
| { | |
| "mirchi_name": "Byadgi", | |
| "poti_count": 10, | |
| "net_weight": 500, | |
| "rate_per_kg": 20, | |
| "amount": 10000, | |
| "source": "normal" | |
| }, | |
| { | |
| "mirchi_name": "Sankeshwari", | |
| "poti_count": 10, | |
| "net_weight": 500, | |
| "rate_per_kg": 20, | |
| "amount": 10000, | |
| "source": "patti" | |
| } | |
| ], | |
| "payments": [ | |
| { | |
| "amount": 10000, | |
| "mode": "bank", | |
| "reference": "BANK001" | |
| } | |
| ] | |
| }) | |
| assert response.status_code == 201 | |
| data = response.json() | |
| assert data["data"]["is_mixed"] is True | |
| async def test_transaction_with_marathi_names(self, client: AsyncClient): | |
| """Test transaction with Marathi mirchi names""" | |
| # Create party with Marathi name | |
| party_response = await client.post("/api/parties", json={ | |
| "name": "मराठी पक्ष", | |
| "phone": "9876543216", | |
| "city": "सांगली", | |
| "party_type": "awaak" | |
| }) | |
| party_id = party_response.json()["data"]["id"] | |
| # Create transaction with Marathi mirchi name | |
| response = await client.post("/api/transactions", json={ | |
| "bill_date": datetime.now().strftime("%Y-%m-%d"), | |
| "bill_type": "awaak", | |
| "party_id": party_id, | |
| "subtotal": 12000, | |
| "total_amount": 12500, | |
| "paid_amount": 12000, | |
| "balance_amount": 500, | |
| "items": [ | |
| { | |
| "mirchi_name": "ब्याडगी मिरची", | |
| "poti_count": 12, | |
| "net_weight": 600, | |
| "rate_per_kg": 20, | |
| "amount": 12000, | |
| "source": "normal" | |
| } | |
| ], | |
| "payments": [ | |
| { | |
| "amount": 12000, | |
| "mode": "cash" | |
| } | |
| ] | |
| }) | |
| assert response.status_code == 201 | |
| data = response.json() | |
| assert data["data"]["party_name"] == "मराठी पक्ष" | |
| assert data["data"]["items"][0]["mirchi_name"] == "ब्याडगी मिरची" | |
| # ============================================ | |
| # PATTI TRANSACTION TESTS | |
| # ============================================ | |
| class TestPattiTransactions: | |
| """Tests for patti transactions""" | |
| async def test_create_patti_awaak(self, client: AsyncClient): | |
| """Test creating patti awaak (no lot/weight initially)""" | |
| # Create party | |
| party_response = await client.post("/api/parties", json={ | |
| "name": "Patti Holder", | |
| "phone": "9876543217", | |
| "city": "Latur", | |
| "party_type": "awaak" | |
| }) | |
| party_id = party_response.json()["data"]["id"] | |
| # Create patti awaak transaction (no lot required) | |
| response = await client.post("/api/patti-transactions", json={ | |
| "bill_date": datetime.now().strftime("%Y-%m-%d"), | |
| "bill_type": "patti_awaak", | |
| "party_id": party_id, | |
| "subtotal": 8000, | |
| "total_amount": 8500, | |
| "paid_amount": 4000, | |
| "balance_amount": 4500, | |
| "expenses": { | |
| "packing": 100, | |
| "godown": 200, | |
| "commission": 100, | |
| "hamali": 50, | |
| "gaadi_bhade": 50 | |
| }, | |
| "items": [ | |
| { | |
| "mirchi_name": "Local Mirchi", | |
| "poti_count": 8, | |
| "net_weight": 400, | |
| "rate_per_kg": 20, | |
| "amount": 8000 | |
| } | |
| ] | |
| }) | |
| assert response.status_code == 201 | |
| data = response.json() | |
| assert data["data"]["bill_type"] == "patti_awaak" | |
| assert data["data"]["bill_number"].startswith("PA") | |
| # lot_number is optional for patti_awaak | |
| assert data["data"].get("lot_number") is None | |
| async def test_create_patti_jawaak_with_lot(self, client: AsyncClient): | |
| """Test creating patti jawaak (lot mandatory)""" | |
| # Create party | |
| party_response = await client.post("/api/parties", json={ | |
| "name": "Patti Buyer", | |
| "phone": "9876543218", | |
| "city": "Osmanabad", | |
| "party_type": "jawaak" | |
| }) | |
| party_id = party_response.json()["data"]["id"] | |
| # Create patti jawaak transaction (lot required) | |
| response = await client.post("/api/patti-transactions", json={ | |
| "bill_date": datetime.now().strftime("%Y-%m-%d"), | |
| "bill_type": "patti_jawaak", | |
| "party_id": party_id, | |
| "subtotal": 12000, | |
| "total_amount": 12500, | |
| "paid_amount": 12000, | |
| "balance_amount": 500, | |
| "lot_number": "LOT-PJ-001", # MANDATORY for patti_jawaak | |
| "gross_weight": 650, | |
| "verified_net_weight": 600, | |
| "expenses": { | |
| "packing": 150, | |
| "godown": 100, | |
| "commission": 150, | |
| "hamali": 50, | |
| "gaadi_bhade": 50 | |
| }, | |
| "items": [ | |
| { | |
| "mirchi_name": "Premium Mirchi", | |
| "poti_count": 12, | |
| "net_weight": 600, | |
| "rate_per_kg": 20, | |
| "amount": 12000 | |
| } | |
| ] | |
| }) | |
| assert response.status_code == 201 | |
| data = response.json() | |
| assert data["data"]["bill_type"] == "patti_jawaak" | |
| assert data["data"]["bill_number"].startswith("PJ") | |
| assert data["data"]["lot_number"] == "LOT-PJ-001" | |
| assert data["data"]["gross_weight"] == 650 | |
| assert data["data"]["verified_net_weight"] == 600 | |
| async def test_patti_jawaak_without_lot_fails(self, client: AsyncClient): | |
| """Test that patti jawaak without lot_number fails""" | |
| # Create party | |
| party_response = await client.post("/api/parties", json={ | |
| "name": "Test Party", | |
| "phone": "9876543219", | |
| "city": "Beed", | |
| "party_type": "jawaak" | |
| }) | |
| party_id = party_response.json()["data"]["id"] | |
| # Try to create patti jawaak without lot (should fail) | |
| response = await client.post("/api/patti-transactions", json={ | |
| "bill_date": datetime.now().strftime("%Y-%m-%d"), | |
| "bill_type": "patti_jawaak", | |
| "party_id": party_id, | |
| "subtotal": 10000, | |
| "total_amount": 10500, | |
| "paid_amount": 10000, | |
| "balance_amount": 500, | |
| # lot_number is MISSING - should fail | |
| "items": [ | |
| { | |
| "mirchi_name": "Test Mirchi", | |
| "poti_count": 10, | |
| "net_weight": 500, | |
| "rate_per_kg": 20, | |
| "amount": 10000 | |
| } | |
| ] | |
| }) | |
| assert response.status_code == 400 | |
| assert "lot number" in response.json()["detail"].lower() | |
| # ============================================ | |
| # PAYMENT TESTS | |
| # ============================================ | |
| class TestPayments: | |
| """Tests for payment operations""" | |
| async def test_update_payment(self, client: AsyncClient): | |
| """Test updating payment for transaction""" | |
| # Create party and transaction | |
| party_response = await client.post("/api/parties", json={ | |
| "name": "Payment Test Party", | |
| "phone": "9876543220", | |
| "city": "Aurangabad", | |
| "party_type": "awaak" | |
| }) | |
| party_id = party_response.json()["data"]["id"] | |
| txn_response = await client.post("/api/transactions", json={ | |
| "bill_date": datetime.now().strftime("%Y-%m-%d"), | |
| "bill_type": "awaak", | |
| "party_id": party_id, | |
| "subtotal": 10000, | |
| "total_amount": 10000, | |
| "paid_amount": 5000, | |
| "balance_amount": 5000, | |
| "items": [ | |
| { | |
| "mirchi_name": "Test", | |
| "poti_count": 10, | |
| "net_weight": 500, | |
| "rate_per_kg": 20, | |
| "amount": 10000, | |
| "source": "normal" | |
| } | |
| ], | |
| "payments": [ | |
| {"amount": 5000, "mode": "cash"} | |
| ] | |
| }) | |
| txn_id = txn_response.json()["data"]["id"] | |
| # Update payment | |
| response = await client.post(f"/api/transactions/{txn_id}/payment?amount=3000") | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert data["data"]["paid_amount"] == 8000 | |
| assert data["data"]["balance_amount"] == 2000 | |
| # ============================================ | |
| # REVERT TESTS | |
| # ============================================ | |
| class TestReverts: | |
| """Tests for revert operations""" | |
| async def test_revert_transaction(self, client: AsyncClient): | |
| """Test reverting a transaction""" | |
| # Create party and transaction | |
| party_response = await client.post("/api/parties", json={ | |
| "name": "Revert Test Party", | |
| "phone": "9876543221", | |
| "city": "Nanded", | |
| "party_type": "awaak" | |
| }) | |
| party_id = party_response.json()["data"]["id"] | |
| txn_response = await client.post("/api/transactions", json={ | |
| "bill_date": datetime.now().strftime("%Y-%m-%d"), | |
| "bill_type": "awaak", | |
| "party_id": party_id, | |
| "subtotal": 5000, | |
| "total_amount": 5000, | |
| "paid_amount": 0, | |
| "balance_amount": 5000, | |
| "items": [ | |
| { | |
| "mirchi_name": "Test", | |
| "poti_count": 5, | |
| "net_weight": 250, | |
| "rate_per_kg": 20, | |
| "amount": 5000, | |
| "source": "normal" | |
| } | |
| ], | |
| "payments": [] | |
| }) | |
| txn_id = txn_response.json()["data"]["id"] | |
| # Revert transaction | |
| response = await client.post(f"/api/transactions/{txn_id}/revert") | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert data["success"] is True | |
| async def test_revert_patti_transaction(self, client: AsyncClient): | |
| """Test reverting a patti transaction""" | |
| # Create party and patti transaction | |
| party_response = await client.post("/api/parties", json={ | |
| "name": "Patti Revert Test", | |
| "phone": "9876543222", | |
| "city": "Parbhani", | |
| "party_type": "awaak" | |
| }) | |
| party_id = party_response.json()["data"]["id"] | |
| txn_response = await client.post("/api/patti-transactions", json={ | |
| "bill_date": datetime.now().strftime("%Y-%m-%d"), | |
| "bill_type": "patti_awaak", | |
| "party_id": party_id, | |
| "subtotal": 6000, | |
| "total_amount": 6000, | |
| "paid_amount": 0, | |
| "balance_amount": 6000, | |
| "items": [ | |
| { | |
| "mirchi_name": "Test", | |
| "poti_count": 6, | |
| "net_weight": 300, | |
| "rate_per_kg": 20, | |
| "amount": 6000 | |
| } | |
| ] | |
| }) | |
| txn_id = txn_response.json()["data"]["id"] | |
| # Revert patti transaction | |
| response = await client.post(f"/api/patti-transactions/{txn_id}/revert") | |
| assert response.status_code == 200 | |
| # ============================================ | |
| # SEARCH TESTS | |
| # ============================================ | |
| class TestSearch: | |
| """Tests for search functionality""" | |
| async def test_search_by_party_name(self, client: AsyncClient): | |
| """Test searching transactions by party name""" | |
| # Create party with unique name | |
| party_response = await client.post("/api/parties", json={ | |
| "name": "Unique Search Party XYZ", | |
| "phone": "9876543223", | |
| "city": "Jalna", | |
| "party_type": "awaak" | |
| }) | |
| party_id = party_response.json()["data"]["id"] | |
| # Create transaction | |
| await client.post("/api/transactions", json={ | |
| "bill_date": datetime.now().strftime("%Y-%m-%d"), | |
| "bill_type": "awaak", | |
| "party_id": party_id, | |
| "subtotal": 1000, | |
| "total_amount": 1000, | |
| "paid_amount": 1000, | |
| "balance_amount": 0, | |
| "items": [ | |
| { | |
| "mirchi_name": "Test", | |
| "poti_count": 1, | |
| "net_weight": 50, | |
| "rate_per_kg": 20, | |
| "amount": 1000, | |
| "source": "normal" | |
| } | |
| ], | |
| "payments": [{"amount": 1000, "mode": "cash"}] | |
| }) | |
| # Search by party name | |
| response = await client.get("/api/transactions?search=Unique Search Party") | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert data["total"] >= 1 | |
| async def test_search_marathi_text(self, client: AsyncClient): | |
| """Test searching with Marathi text""" | |
| # Create party with Marathi name | |
| party_response = await client.post("/api/parties", json={ | |
| "name": "शोध पक्ष", | |
| "phone": "9876543224", | |
| "city": "मुंबई", | |
| "party_type": "awaak" | |
| }) | |
| party_id = party_response.json()["data"]["id"] | |
| # Create transaction | |
| await client.post("/api/transactions", json={ | |
| "bill_date": datetime.now().strftime("%Y-%m-%d"), | |
| "bill_type": "awaak", | |
| "party_id": party_id, | |
| "subtotal": 1000, | |
| "total_amount": 1000, | |
| "paid_amount": 1000, | |
| "balance_amount": 0, | |
| "items": [ | |
| { | |
| "mirchi_name": "मिरची", | |
| "poti_count": 1, | |
| "net_weight": 50, | |
| "rate_per_kg": 20, | |
| "amount": 1000, | |
| "source": "normal" | |
| } | |
| ], | |
| "payments": [{"amount": 1000, "mode": "cash"}] | |
| }) | |
| # Search with Marathi text | |
| response = await client.get("/api/transactions?search=शोध") | |
| assert response.status_code == 200 | |
| # ============================================ | |
| # PARTY RENAME IMPACT TESTS | |
| # ============================================ | |
| class TestPartyRenameImpact: | |
| """Tests for party rename impact on transactions""" | |
| async def test_rename_updates_transaction_search(self, client: AsyncClient): | |
| """Test that renaming party updates party_name_current in transactions""" | |
| # Create party | |
| party_response = await client.post("/api/parties", json={ | |
| "name": "Original Name", | |
| "phone": "9876543225", | |
| "city": "Pune", | |
| "party_type": "awaak" | |
| }) | |
| party_id = party_response.json()["data"]["id"] | |
| # Create transaction | |
| txn_response = await client.post("/api/transactions", json={ | |
| "bill_date": datetime.now().strftime("%Y-%m-%d"), | |
| "bill_type": "awaak", | |
| "party_id": party_id, | |
| "subtotal": 1000, | |
| "total_amount": 1000, | |
| "paid_amount": 1000, | |
| "balance_amount": 0, | |
| "items": [ | |
| { | |
| "mirchi_name": "Test", | |
| "poti_count": 1, | |
| "net_weight": 50, | |
| "rate_per_kg": 20, | |
| "amount": 1000, | |
| "source": "normal" | |
| } | |
| ], | |
| "payments": [{"amount": 1000, "mode": "cash"}] | |
| }) | |
| txn_id = txn_response.json()["data"]["id"] | |
| # Rename party | |
| await client.put(f"/api/parties/{party_id}", json={"name": "Renamed Party"}) | |
| # Get transaction - should have updated party_name_current | |
| response = await client.get(f"/api/transactions/{txn_id}") | |
| assert response.status_code == 200 | |
| data = response.json() | |
| # Original name snapshot should remain | |
| assert data["data"]["party_name"] == "Original Name" | |
| # Current name should be updated for search | |
| assert data["data"]["party_name_current"] == "Renamed Party" | |
| # Search by new name should find the transaction | |
| search_response = await client.get("/api/transactions?search=Renamed Party") | |
| assert search_response.status_code == 200 | |
| assert search_response.json()["total"] >= 1 | |
| if __name__ == "__main__": | |
| pytest.main([__file__, "-v", "--tb=short"]) | |