Spaces:
Sleeping
Sleeping
| """ | |
| Invoice Generation System - Test Script | |
| This script tests the complete invoice generation flow: | |
| 1. Get available tickets | |
| 2. Generate invoice | |
| 3. View invoice (public) | |
| 4. Export CSV | |
| 5. Regenerate token | |
| Usage: | |
| python scripts/test_invoice_generation.py | |
| """ | |
| import requests | |
| import json | |
| import sys | |
| from datetime import datetime | |
| # Configuration | |
| BASE_URL = "http://localhost:8000/api/v1" | |
| AUTH_TOKEN = "YOUR_AUTH_TOKEN_HERE" # Replace with actual token | |
| CONTRACTOR_ID = "YOUR_CONTRACTOR_ID" # Replace with actual UUID | |
| CLIENT_ID = "YOUR_CLIENT_ID" # Replace with actual UUID | |
| PROJECT_ID = "YOUR_PROJECT_ID" # Replace with actual UUID | |
| HEADERS = { | |
| "Authorization": f"Bearer {AUTH_TOKEN}", | |
| "Content-Type": "application/json" | |
| } | |
| def print_section(title): | |
| """Print section header""" | |
| print("\n" + "=" * 60) | |
| print(f" {title}") | |
| print("=" * 60) | |
| def print_success(message): | |
| """Print success message""" | |
| print(f"β {message}") | |
| def print_error(message): | |
| """Print error message""" | |
| print(f"β {message}") | |
| def print_info(message): | |
| """Print info message""" | |
| print(f"βΉοΈ {message}") | |
| def test_get_available_tickets(): | |
| """Test getting available tickets""" | |
| print_section("1. Get Available Tickets") | |
| try: | |
| response = requests.get( | |
| f"{BASE_URL}/invoices/available-tickets", | |
| params={ | |
| "contractor_id": CONTRACTOR_ID, | |
| "project_id": PROJECT_ID | |
| }, | |
| headers=HEADERS | |
| ) | |
| if response.status_code == 200: | |
| data = response.json() | |
| tickets = data.get("tickets", []) | |
| print_success(f"Found {len(tickets)} available tickets") | |
| if tickets: | |
| print_info("Sample ticket:") | |
| ticket = tickets[0] | |
| print(f" - ID: {ticket['id']}") | |
| print(f" - Name: {ticket.get('ticket_name', 'N/A')}") | |
| print(f" - Type: {ticket['ticket_type']}") | |
| print(f" - Images: {ticket['images_count']}") | |
| print(f" - Sales Order: {ticket.get('sales_order_number', 'N/A')}") | |
| return [t['id'] for t in tickets[:2]] # Return first 2 ticket IDs | |
| else: | |
| print_error("No available tickets found") | |
| print_info("Create some completed tickets first:") | |
| print(" UPDATE tickets SET status='completed', completed_at=NOW(), is_invoiced=false WHERE id='YOUR_TICKET_ID';") | |
| return None | |
| else: | |
| print_error(f"Failed: {response.status_code}") | |
| print(response.text) | |
| return None | |
| except Exception as e: | |
| print_error(f"Exception: {str(e)}") | |
| return None | |
| def test_generate_invoice(ticket_ids): | |
| """Test generating invoice""" | |
| print_section("2. Generate Invoice") | |
| if not ticket_ids: | |
| print_error("No ticket IDs provided") | |
| return None | |
| try: | |
| payload = { | |
| "contractor_id": CONTRACTOR_ID, | |
| "client_id": CLIENT_ID, | |
| "project_id": PROJECT_ID, | |
| "ticket_ids": ticket_ids, | |
| "title": f"Test Invoice - {datetime.now().strftime('%Y-%m-%d %H:%M')}", | |
| "notes": "This is a test invoice generated by the test script" | |
| } | |
| response = requests.post( | |
| f"{BASE_URL}/invoices/generate", | |
| headers=HEADERS, | |
| json=payload | |
| ) | |
| if response.status_code == 200: | |
| data = response.json() | |
| print_success("Invoice generated successfully") | |
| print(f" - Invoice ID: {data['invoice_id']}") | |
| print(f" - Invoice Number: {data['invoice_number']}") | |
| print(f" - Tickets: {data['tickets_count']}") | |
| print(f" - Viewing Link: {data['viewing_link']}") | |
| print(f" - CSV Link: {data['csv_download_link']}") | |
| print(f" - Notification Created: {data['notification_created']}") | |
| return data | |
| else: | |
| print_error(f"Failed: {response.status_code}") | |
| print(response.text) | |
| return None | |
| except Exception as e: | |
| print_error(f"Exception: {str(e)}") | |
| return None | |
| def test_view_invoice(viewing_link): | |
| """Test viewing invoice (public - no auth)""" | |
| print_section("3. View Invoice (Public)") | |
| if not viewing_link: | |
| print_error("No viewing link provided") | |
| return False | |
| try: | |
| # Extract token from link | |
| token = viewing_link.split("token=")[1] if "token=" in viewing_link else None | |
| if not token: | |
| print_error("Could not extract token from link") | |
| return False | |
| response = requests.get( | |
| f"{BASE_URL}/invoices/view", | |
| params={"token": token} | |
| ) | |
| if response.status_code == 200: | |
| data = response.json() | |
| invoice = data.get("invoice", {}) | |
| print_success("Invoice viewed successfully") | |
| print(f" - Invoice Number: {invoice.get('invoice_number')}") | |
| print(f" - Line Items: {len(invoice.get('line_items', []))}") | |
| print(f" - Times Viewed: {data.get('times_viewed')}") | |
| print(f" - Token Expires: {data.get('token_expires_at')}") | |
| # Check if ticket details are enriched | |
| line_items = invoice.get('line_items', []) | |
| if line_items: | |
| first_item = line_items[0] | |
| if 'ticket_details' in first_item: | |
| details = first_item['ticket_details'] | |
| print_info("Ticket details enriched:") | |
| print(f" - Images: {details.get('images_count', 0)}") | |
| print(f" - Completion Data: {bool(details.get('completion_data'))}") | |
| print(f" - Location: {bool(details.get('work_location'))}") | |
| return True | |
| else: | |
| print_error(f"Failed: {response.status_code}") | |
| print(response.text) | |
| return False | |
| except Exception as e: | |
| print_error(f"Exception: {str(e)}") | |
| return False | |
| def test_export_csv(invoice_id): | |
| """Test CSV export""" | |
| print_section("4. Export CSV") | |
| if not invoice_id: | |
| print_error("No invoice ID provided") | |
| return False | |
| try: | |
| response = requests.get( | |
| f"{BASE_URL}/invoices/{invoice_id}/export/csv", | |
| headers=HEADERS | |
| ) | |
| if response.status_code == 200: | |
| # Save CSV to file | |
| filename = f"invoice_{invoice_id}.csv" | |
| with open(filename, "wb") as f: | |
| f.write(response.content) | |
| print_success(f"CSV exported successfully: {filename}") | |
| # Show first few lines | |
| lines = response.content.decode('utf-8').split('\n') | |
| print_info("CSV Preview (first 3 lines):") | |
| for i, line in enumerate(lines[:3]): | |
| print(f" {i+1}: {line[:100]}...") | |
| return True | |
| else: | |
| print_error(f"Failed: {response.status_code}") | |
| print(response.text) | |
| return False | |
| except Exception as e: | |
| print_error(f"Exception: {str(e)}") | |
| return False | |
| def test_regenerate_token(invoice_id): | |
| """Test token regeneration""" | |
| print_section("5. Regenerate Token") | |
| if not invoice_id: | |
| print_error("No invoice ID provided") | |
| return False | |
| try: | |
| response = requests.post( | |
| f"{BASE_URL}/invoices/{invoice_id}/regenerate-token", | |
| headers=HEADERS, | |
| json={"expires_in_days": 30} | |
| ) | |
| if response.status_code == 200: | |
| data = response.json() | |
| print_success("Token regenerated successfully") | |
| print(f" - New Link: {data['viewing_link']}") | |
| print(f" - Expires At: {data['expires_at']}") | |
| return True | |
| else: | |
| print_error(f"Failed: {response.status_code}") | |
| print(response.text) | |
| return False | |
| except Exception as e: | |
| print_error(f"Exception: {str(e)}") | |
| return False | |
| def main(): | |
| """Run all tests""" | |
| print("\n" + "π" * 30) | |
| print(" Invoice Generation System - Test Script") | |
| print("π" * 30) | |
| # Check configuration | |
| if AUTH_TOKEN == "YOUR_AUTH_TOKEN_HERE": | |
| print_error("Please configure AUTH_TOKEN in the script") | |
| sys.exit(1) | |
| if CONTRACTOR_ID == "YOUR_CONTRACTOR_ID": | |
| print_error("Please configure CONTRACTOR_ID in the script") | |
| sys.exit(1) | |
| # Run tests | |
| ticket_ids = test_get_available_tickets() | |
| if ticket_ids: | |
| invoice_data = test_generate_invoice(ticket_ids) | |
| if invoice_data: | |
| test_view_invoice(invoice_data['viewing_link']) | |
| test_export_csv(invoice_data['invoice_id']) | |
| test_regenerate_token(invoice_data['invoice_id']) | |
| # Summary | |
| print_section("Test Summary") | |
| print("β All tests completed") | |
| print("\nNext steps:") | |
| print("1. Check notifications in the database") | |
| print("2. Verify tickets are marked as invoiced") | |
| print("3. Review audit logs") | |
| print("4. Test the viewing link in a browser") | |
| print("\n" + "π" * 30 + "\n") | |
| if __name__ == "__main__": | |
| main() | |