Files
orion/scripts/test_vendor_management.py
Samir Boulahtit b8a46e1746 fix: protect critical re-export imports from linter removal
Problem:
- Ruff removed 'from app.core.database import Base' from models/database/base.py
- Import appeared "unused" (F401) but was actually a critical re-export
- Caused ImportError: cannot import name 'Base' at runtime
- Re-export pattern: import in one file to export from package

Solution:
1. Added F401 ignore for models/database/base.py in pyproject.toml
2. Created scripts/verify_critical_imports.py verification script
3. Integrated verification into make check and CI pipeline
4. Updated documentation with explanation

New Verification Script:
- Checks all critical re-export imports exist
- Detects import variations (parentheses, 'as' clauses)
- Handles SQLAlchemy declarative_base alternatives
- Runs as part of make check automatically

Protected Files:
- models/database/base.py - Re-exports Base for all models
- models/__init__.py - Exports Base for Alembic
- models/database/__init__.py - Exports Base from package
- All __init__.py files (already protected)

Makefile Changes:
- make verify-imports - Run import verification
- make check - Now includes verify-imports
- make ci - Includes verify-imports in pipeline

Documentation Updated:
- Code quality guide explains re-export protection
- Pre-commit workflow includes verification
- Examples of why re-exports matter

This prevents future issues where linters remove seemingly
"unused" imports that are actually critical for application structure.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 20:10:22 +01:00

263 lines
8.0 KiB
Python

#!/usr/bin/env python3
"""
Test script for vendor management features.
Tests:
- Create vendor with both emails
- Create vendor with only owner_email
- Update vendor (contact_email)
- Transfer ownership
"""
import requests
BASE_URL = "http://localhost:8000"
ADMIN_TOKEN = None # Will be set after login
def login_admin():
"""Login as admin and get token."""
global ADMIN_TOKEN
response = requests.post(
f"{BASE_URL}/api/v1/admin/auth/login", # ✅ Changed: added /admin/
json={
"username": "admin", # Replace with your admin username
"password": "admin123", # Replace with your admin password
},
)
if response.status_code == 200:
data = response.json()
ADMIN_TOKEN = data["access_token"]
print("✅ Admin login successful")
return True
print(f"❌ Admin login failed: {response.status_code}")
print(response.text)
return False
def get_headers():
"""Get authorization headers."""
return {
"Authorization": f"Bearer {ADMIN_TOKEN}",
"Content-Type": "application/json",
}
def test_create_vendor_with_both_emails():
"""Test creating vendor with both owner_email and contact_email."""
print("\n" + "=" * 60)
print("TEST 1: Create vendor with both emails")
print("=" * 60)
vendor_data = {
"vendor_code": "TESTDUAL",
"name": "Test Dual Email Vendor",
"subdomain": "testdual",
"owner_email": "owner@testdual.com",
"contact_email": "contact@testdual.com",
"description": "Test vendor with separate emails",
}
response = requests.post(
f"{BASE_URL}/api/v1/admin/vendors", headers=get_headers(), json=vendor_data
)
if response.status_code == 200:
data = response.json()
print("✅ Vendor created successfully")
print("\n📧 Emails:")
print(f" Owner Email: {data['owner_email']}")
print(f" Contact Email: {data['contact_email']}")
print("\n🔑 Credentials:")
print(f" Username: {data['owner_username']}")
print(f" Password: {data['temporary_password']}")
print(f"\n🔗 Login URL: {data['login_url']}")
return data["id"]
print(f"❌ Failed: {response.status_code}")
print(response.text)
return None
def test_create_vendor_single_email():
"""Test creating vendor with only owner_email (contact should default)."""
print("\n" + "=" * 60)
print("TEST 2: Create vendor with only owner_email")
print("=" * 60)
vendor_data = {
"vendor_code": "TESTSINGLE",
"name": "Test Single Email Vendor",
"subdomain": "testsingle",
"owner_email": "owner@testsingle.com",
"description": "Test vendor with single email",
}
response = requests.post(
f"{BASE_URL}/api/v1/admin/vendors", headers=get_headers(), json=vendor_data
)
if response.status_code == 200:
data = response.json()
print("✅ Vendor created successfully")
print("\n📧 Emails:")
print(f" Owner Email: {data['owner_email']}")
print(f" Contact Email: {data['contact_email']}")
if data["owner_email"] == data["contact_email"]:
print("✅ Contact email correctly defaulted to owner email")
else:
print("❌ Contact email should have defaulted to owner email")
return data["id"]
print(f"❌ Failed: {response.status_code}")
print(response.text)
return None
def test_update_vendor_contact_email(vendor_id):
"""Test updating vendor's contact email."""
print("\n" + "=" * 60)
print(f"TEST 3: Update vendor {vendor_id} contact_email")
print("=" * 60)
update_data = {
"contact_email": "newcontact@business.com",
"name": "Updated Vendor Name",
}
response = requests.put(
f"{BASE_URL}/api/v1/admin/vendors/{vendor_id}",
headers=get_headers(),
json=update_data,
)
if response.status_code == 200:
data = response.json()
print("✅ Vendor updated successfully")
print("\n📧 Emails after update:")
print(f" Owner Email: {data['owner_email']} (unchanged)")
print(f" Contact Email: {data['contact_email']} (updated)")
print(f"\n📝 Name: {data['name']} (updated)")
return True
print(f"❌ Failed: {response.status_code}")
print(response.text)
return False
def test_get_vendor_details(vendor_id):
"""Test getting vendor details with owner info."""
print("\n" + "=" * 60)
print(f"TEST 4: Get vendor {vendor_id} details")
print("=" * 60)
response = requests.get(
f"{BASE_URL}/api/v1/admin/vendors/{vendor_id}", headers=get_headers()
)
if response.status_code == 200:
data = response.json()
print("✅ Vendor details retrieved")
print("\n📋 Vendor Info:")
print(f" ID: {data['id']}")
print(f" Code: {data['vendor_code']}")
print(f" Name: {data['name']}")
print(f" Subdomain: {data['subdomain']}")
print("\n👤 Owner Info:")
print(f" Username: {data['owner_username']}")
print(f" Email: {data['owner_email']}")
print("\n📧 Contact Info:")
print(f" Email: {data['contact_email']}")
print(f" Phone: {data.get('contact_phone', 'N/A')}")
return True
print(f"❌ Failed: {response.status_code}")
print(response.text)
return False
def test_transfer_ownership(vendor_id, new_owner_user_id):
"""Test transferring vendor ownership."""
print("\n" + "=" * 60)
print(f"TEST 5: Transfer ownership of vendor {vendor_id}")
print("=" * 60)
# First, get current owner info
response = requests.get(
f"{BASE_URL}/api/v1/admin/vendors/{vendor_id}", headers=get_headers()
)
if response.status_code == 200:
current_data = response.json()
print("\n📋 Current Owner:")
print(f" User ID: {current_data['owner_user_id']}")
print(f" Username: {current_data['owner_username']}")
print(f" Email: {current_data['owner_email']}")
# Transfer ownership
transfer_data = {
"new_owner_user_id": new_owner_user_id,
"confirm_transfer": True,
"transfer_reason": "Testing ownership transfer feature",
}
response = requests.post(
f"{BASE_URL}/api/v1/admin/vendors/{vendor_id}/transfer-ownership",
headers=get_headers(),
json=transfer_data,
)
if response.status_code == 200:
data = response.json()
print(f"\n{data['message']}")
print("\n👤 Old Owner:")
print(f" ID: {data['old_owner']['id']}")
print(f" Username: {data['old_owner']['username']}")
print(f" Email: {data['old_owner']['email']}")
print("\n👤 New Owner:")
print(f" ID: {data['new_owner']['id']}")
print(f" Username: {data['new_owner']['username']}")
print(f" Email: {data['new_owner']['email']}")
print(f"\n📝 Reason: {data['transfer_reason']}")
print(f"⏰ Transferred at: {data['transferred_at']}")
return True
print(f"❌ Failed: {response.status_code}")
print(response.text)
return False
def main():
"""Run all tests."""
print("\n🧪 Starting Vendor Management Tests")
print("=" * 60)
# Login first
if not login_admin():
print("\n❌ Cannot proceed without admin login")
return
# Test 1: Create with both emails
vendor_id_1 = test_create_vendor_with_both_emails()
# Test 2: Create with single email
vendor_id_2 = test_create_vendor_single_email()
if vendor_id_1:
# Test 3: Update contact email
test_update_vendor_contact_email(vendor_id_1)
# Test 4: Get vendor details
test_get_vendor_details(vendor_id_1)
# Test 5: Transfer ownership (you need to provide a valid user ID)
# Uncomment and replace with actual user ID to test
# test_transfer_ownership(vendor_id_1, new_owner_user_id=2)
print("\n" + "=" * 60)
print("✅ All tests completed!")
print("=" * 60)
if __name__ == "__main__":
main()