{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "19217905-6ff8-4a85-81f7-f12af6f3f89c",
   "metadata": {},
   "source": [
    "# Complete PyCharter Workflow: From Pydantic Model to Database and Back\n",
    "\n",
    "This notebook demonstrates the complete workflow:\n",
    "1. Convert Pydantic model to JSON Schema\n",
    "2. Parse contract YAML and decompose into components\n",
    "3. Store all components in PostgreSQL metadata store\n",
    "4. Extract from store and reconstruct contract\n",
    "5. Generate Pydantic model from reconstructed contract\n",
    "\n",
    "## Prerequisites\n",
    "\n",
    "Before running this notebook, ensure you have:\n",
    "1. Initialized the database: `pycharter db init postgresql://user:pass@localhost/dbname`\n",
    "2. (Optional) Seeded initial data: `pycharter db seed data/seed postgresql://user:pass@localhost/dbname`\n",
    "3. PostgreSQL running and accessible"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "e224192c-261e-45e4-80c1-595fee29b079",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "✓ Loaded 905 records from CSV\n"
     ]
    }
   ],
   "source": [
    "import json\n",
    "import os\n",
    "from typing import Optional, Dict, Any, List\n",
    "import sys\n",
    "\n",
    "from pydantic import BaseModel\n",
    "import pandas as pd\n",
    "\n",
    "from pycharter import (\n",
    "    # Service 1: Contract Parser\n",
    "    parse_contract_file,\n",
    "    ContractMetadata,\n",
    "    # Service 2: Metadata Store\n",
    "    PostgresMetadataStore,\n",
    "    # Service 3: Pydantic Generator\n",
    "    from_dict,\n",
    "    # Service 4: JSON Schema Converter\n",
    "    to_dict,\n",
    "    # Service 5: Runtime Validator\n",
    "    get_model_from_contract,\n",
    "    # Service 6: Contract Builder\n",
    "    build_contract_from_store,\n",
    ")\n",
    "\n",
    "# Setup paths\n",
    "ROOT_DIR = os.path.join('..')\n",
    "DATA_DIR = os.path.join(ROOT_DIR, 'data')\n",
    "EXAMPLES_DIR = os.path.join(DATA_DIR, 'examples')\n",
    "AIRCRAFT_DIR = os.path.join(EXAMPLES_DIR, 'aircraft')\n",
    "AIRCRAFT_CONTRACT = os.path.join(AIRCRAFT_DIR, 'aircraft_contract.yaml')\n",
    "\n",
    "# Add paths for importing aircraft models\n",
    "sys.path.append(ROOT_DIR)\n",
    "sys.path.append(AIRCRAFT_DIR)\n",
    "\n",
    "# Import Aircraft model\n",
    "from aircraft_models import Aircraft\n",
    "\n",
    "# Load sample data (if available)\n",
    "csv_path = os.path.join(AIRCRAFT_DIR, 'aircraft.csv')\n",
    "if os.path.exists(csv_path):\n",
    "    df = pd.read_csv(csv_path)\n",
    "    print(f\"✓ Loaded {len(df)} records from CSV\")\n",
    "else:\n",
    "    print(\"⚠ CSV file not found, will use sample data from model\")\n",
    "    df = None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "893fce3e-db15-48b7-8b6c-f301efbe23ff",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "======================================================================\n",
      "Step 1: Convert Pydantic Model to JSON Schema\n",
      "======================================================================\n",
      "✓ Converted Aircraft model to JSON Schema\n",
      "  Schema title: Aircraft\n",
      "  Schema version: 1.0.0\n",
      "  Number of properties: 41\n"
     ]
    }
   ],
   "source": [
    "# Step 1: Convert Pydantic Model to JSON Schema\n",
    "print(\"=\" * 70)\n",
    "print(\"Step 1: Convert Pydantic Model to JSON Schema\")\n",
    "print(\"=\" * 70)\n",
    "\n",
    "# Convert Aircraft Pydantic model to JSON Schema\n",
    "aircraft_schema = to_dict(Aircraft)\n",
    "print(f\"✓ Converted Aircraft model to JSON Schema\")\n",
    "print(f\"  Schema title: {aircraft_schema.get('title')}\")\n",
    "print(f\"  Schema version: {aircraft_schema.get('version')}\")\n",
    "print(f\"  Number of properties: {len(aircraft_schema.get('properties', {}))}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "4fdfec1e-e767-434d-ad3f-997332bb2ac3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "======================================================================\n",
      "Step 2: Parse Contract YAML and Decompose into Components\n",
      "======================================================================\n",
      "✓ Parsed contract file: ../data/examples/aircraft/aircraft_contract.yaml\n",
      "  Schema version: 1.0.0\n",
      "  Metadata version: 1.0.0\n",
      "  Ownership: operations-team / data-engineering\n",
      "  Coercion rules: 40 fields\n",
      "  Validation rules: 34 fields\n",
      "  Governance rules: Yes\n"
     ]
    }
   ],
   "source": [
    "# Step 2: Parse Contract YAML and Decompose into Components\n",
    "print(\"\\n\" + \"=\" * 70)\n",
    "print(\"Step 2: Parse Contract YAML and Decompose into Components\")\n",
    "print(\"=\" * 70)\n",
    "\n",
    "# Parse the contract file\n",
    "contract_metadata = parse_contract_file(AIRCRAFT_CONTRACT, validate=False)\n",
    "print(f\"✓ Parsed contract file: {AIRCRAFT_CONTRACT}\")\n",
    "\n",
    "# Extract components\n",
    "schema = contract_metadata.schema\n",
    "metadata = contract_metadata.metadata\n",
    "ownership = contract_metadata.ownership\n",
    "governance_rules = contract_metadata.governance_rules\n",
    "versions = contract_metadata.versions\n",
    "\n",
    "print(f\"  Schema version: {versions.get('schema', 'N/A')}\")\n",
    "print(f\"  Metadata version: {versions.get('metadata', 'N/A')}\")\n",
    "print(f\"  Ownership: {ownership.get('owner', 'N/A')} / {ownership.get('team', 'N/A')}\")\n",
    "\n",
    "# Extract coercion and validation rules from schema properties\n",
    "# (They're embedded in the schema properties in the contract YAML)\n",
    "coercion_rules = {}\n",
    "validation_rules = {}\n",
    "\n",
    "if \"properties\" in schema:\n",
    "    for field_name, field_schema in schema[\"properties\"].items():\n",
    "        if isinstance(field_schema, dict):\n",
    "            # Extract coercion rule\n",
    "            if \"coercion\" in field_schema:\n",
    "                coercion_rules[field_name] = field_schema[\"coercion\"]\n",
    "            \n",
    "            # Extract validation rules\n",
    "            if \"validations\" in field_schema:\n",
    "                validation_rules[field_name] = field_schema[\"validations\"]\n",
    "\n",
    "print(f\"  Coercion rules: {len(coercion_rules)} fields\")\n",
    "print(f\"  Validation rules: {len(validation_rules)} fields\")\n",
    "print(f\"  Governance rules: {'Yes' if governance_rules else 'No'}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1f6e387c-bcee-48d3-a27b-c505ceefe6b0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "======================================================================\n",
      "Step 3: Store All Components in PostgreSQL Metadata Store\n",
      "======================================================================\n",
      "✓ Connected to PostgreSQL metadata store\n",
      "✓ Stored schema (ID: 82bb9a54-36d2-4f90-9651-3b6cd72aacec, version: 1.0.0)\n",
      "✓ Stored metadata with ownership and governance rules\n",
      "✓ Stored coercion rules (version: 1.0.0)\n",
      "✓ Stored validation rules (version: 1.0.0)\n",
      "\n",
      "✓ All components stored successfully (Schema ID: 82bb9a54-36d2-4f90-9651-3b6cd72aacec)\n"
     ]
    }
   ],
   "source": [
    "# Step 3: Store All Components in PostgreSQL Metadata Store\n",
    "print(\"\\n\" + \"=\" * 70)\n",
    "print(\"Step 3: Store All Components in PostgreSQL Metadata Store\")\n",
    "print(\"=\" * 70)\n",
    "\n",
    "# Connect to PostgreSQL\n",
    "connection_string = \"postgresql://postgres:1234567890@localhost:5432/postgres\"\n",
    "store = PostgresMetadataStore(connection_string=connection_string)\n",
    "store.connect()\n",
    "print(\"✓ Connected to PostgreSQL metadata store\")\n",
    "\n",
    "# Store schema (use the schema from the contract, which has version info)\n",
    "schema_version = versions.get(\"schema\", schema.get(\"version\", \"1.0.0\"))\n",
    "schema_id = store.store_schema(\n",
    "    schema_name=\"aircraft\",\n",
    "    schema=schema,\n",
    "    version=schema_version\n",
    ")\n",
    "print(f\"✓ Stored schema (ID: {schema_id}, version: {schema_version})\")\n",
    "\n",
    "# Merge ownership and governance rules into metadata before storing\n",
    "# Ownership and governance are part of metadata, not separate entities\n",
    "metadata_dict = metadata.copy() if metadata else {}\n",
    "if ownership:\n",
    "    metadata_dict[\"business_owners\"] = [ownership.get(\"owner\", \"unknown\")] if ownership.get(\"owner\") else []\n",
    "if governance_rules:\n",
    "    metadata_dict[\"governance_rules\"] = governance_rules\n",
    "\n",
    "# Store metadata once with all information (ownership and governance included)\n",
    "# Note: The new API uses schema_id (not resource_id/resource_type)\n",
    "if metadata_dict:\n",
    "    store.store_metadata(\n",
    "        schema_id=schema_id,\n",
    "        metadata=metadata_dict,\n",
    "        version=schema_version\n",
    "    )\n",
    "    print(f\"✓ Stored metadata (including ownership and governance rules)\")\n",
    "\n",
    "# Store coercion rules\n",
    "if coercion_rules:\n",
    "    coercion_version = versions.get(\"coercion_rules\", \"1.0.0\")\n",
    "    store.store_coercion_rules(\n",
    "        schema_id=schema_id,\n",
    "        coercion_rules=coercion_rules,\n",
    "        version=coercion_version\n",
    "    )\n",
    "    print(f\"✓ Stored coercion rules (version: {coercion_version})\")\n",
    "\n",
    "# Store validation rules\n",
    "if validation_rules:\n",
    "    validation_version = versions.get(\"validation_rules\", \"1.0.0\")\n",
    "    store.store_validation_rules(\n",
    "        schema_id=schema_id,\n",
    "        validation_rules=validation_rules,\n",
    "        version=validation_version\n",
    "    )\n",
    "    print(f\"✓ Stored validation rules (version: {validation_version})\")\n",
    "\n",
    "print(f\"\\n✓ All components stored successfully (Schema ID: {schema_id})\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "1429e69f-16bc-4cc2-8aff-f0f4920956f6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "======================================================================\n",
      "Step 4: Extract from Metadata Store and Reconstruct Contract\n",
      "======================================================================\n",
      "✓ Reconstructed contract from metadata store\n",
      "  Contract keys: ['schema', 'metadata', 'versions']\n",
      "  Schema title: Aircraft\n",
      "  Schema version: 1.0.0\n",
      "  Metadata present: Yes\n"
     ]
    }
   ],
   "source": [
    "# Step 4: Extract from Metadata Store and Reconstruct Contract\n",
    "print(\"\\n\" + \"=\" * 70)\n",
    "print(\"Step 4: Extract from Metadata Store and Reconstruct Contract\")\n",
    "print(\"=\" * 70)\n",
    "\n",
    "# Reconstruct the contract from the metadata store\n",
    "reconstructed_contract = build_contract_from_store(\n",
    "    store=store,\n",
    "    schema_id=schema_id,\n",
    "    version=None,  # Use latest version\n",
    "    include_metadata=True,\n",
    "    include_ownership=True,\n",
    "    include_governance=True\n",
    ")\n",
    "print(f\"✓ Reconstructed contract from metadata store\")\n",
    "print(f\"  Contract keys: {list(reconstructed_contract.keys())}\")\n",
    "\n",
    "# Show what was reconstructed\n",
    "if \"schema\" in reconstructed_contract:\n",
    "    print(f\"  Schema title: {reconstructed_contract['schema'].get('title')}\")\n",
    "    print(f\"  Schema version: {reconstructed_contract['schema'].get('version')}\")\n",
    "if \"metadata\" in reconstructed_contract:\n",
    "    print(f\"  Metadata present: Yes\")\n",
    "if \"ownership\" in reconstructed_contract:\n",
    "    print(f\"  Ownership: {reconstructed_contract['ownership'].get('owner', 'N/A')}\")\n",
    "if \"governance_rules\" in reconstructed_contract:\n",
    "    print(f\"  Governance rules present: Yes\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "f3b0a200-676a-4c97-b504-9528b7e9fe72",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "======================================================================\n",
      "Step 5: Create Pydantic Model from Reconstructed Contract\n",
      "======================================================================\n",
      "✓ Generated Pydantic model: Aircraft\n",
      "\n",
      "Testing model with sample data:\n",
      "⚠ Validation issues found:\n",
      "  - {'type': 'missing', 'loc': ('metadata',), 'msg': 'Field required', 'input': {'registration': 'CACAT', 'valid_since': '01-JAN-14', 'valid_until': '01-OCT-19', 'ac_operator': 'CA ', 'ac_owner': 'CA', 'ac_subtype': 'CAT', 'ac_logical_no': 0, 'ac_state': 'O', 'dry_operating_wgt': 0, 'max_takeoff_wgt': 0, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 0, 'crewsize_cockpit': 2, 'crewsize_cabin': 3, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'CA                            ', 'ac_subtype_name': 'CAT                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': None, 'alt_reg': None, 'record_id': 25391, 'last_update': '25-OCT-24', 'last_update_user_id': 'iocltm', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "  - {'type': 'missing', 'loc': ('REGISTRATION',), 'msg': 'Field required', 'input': {'registration': 'CACAT', 'valid_since': '01-JAN-14', 'valid_until': '01-OCT-19', 'ac_operator': 'CA ', 'ac_owner': 'CA', 'ac_subtype': 'CAT', 'ac_logical_no': 0, 'ac_state': 'O', 'dry_operating_wgt': 0, 'max_takeoff_wgt': 0, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 0, 'crewsize_cockpit': 2, 'crewsize_cabin': 3, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'CA                            ', 'ac_subtype_name': 'CAT                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': None, 'alt_reg': None, 'record_id': 25391, 'last_update': '25-OCT-24', 'last_update_user_id': 'iocltm', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "  - {'type': 'missing', 'loc': ('VALID_SINCE',), 'msg': 'Field required', 'input': {'registration': 'CACAT', 'valid_since': '01-JAN-14', 'valid_until': '01-OCT-19', 'ac_operator': 'CA ', 'ac_owner': 'CA', 'ac_subtype': 'CAT', 'ac_logical_no': 0, 'ac_state': 'O', 'dry_operating_wgt': 0, 'max_takeoff_wgt': 0, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 0, 'crewsize_cockpit': 2, 'crewsize_cabin': 3, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'CA                            ', 'ac_subtype_name': 'CAT                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': None, 'alt_reg': None, 'record_id': 25391, 'last_update': '25-OCT-24', 'last_update_user_id': 'iocltm', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "  - {'type': 'missing', 'loc': ('VALID_UNTIL',), 'msg': 'Field required', 'input': {'registration': 'CACAT', 'valid_since': '01-JAN-14', 'valid_until': '01-OCT-19', 'ac_operator': 'CA ', 'ac_owner': 'CA', 'ac_subtype': 'CAT', 'ac_logical_no': 0, 'ac_state': 'O', 'dry_operating_wgt': 0, 'max_takeoff_wgt': 0, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 0, 'crewsize_cockpit': 2, 'crewsize_cabin': 3, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'CA                            ', 'ac_subtype_name': 'CAT                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': None, 'alt_reg': None, 'record_id': 25391, 'last_update': '25-OCT-24', 'last_update_user_id': 'iocltm', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "  - {'type': 'missing', 'loc': ('AC_OPERATOR',), 'msg': 'Field required', 'input': {'registration': 'CACAT', 'valid_since': '01-JAN-14', 'valid_until': '01-OCT-19', 'ac_operator': 'CA ', 'ac_owner': 'CA', 'ac_subtype': 'CAT', 'ac_logical_no': 0, 'ac_state': 'O', 'dry_operating_wgt': 0, 'max_takeoff_wgt': 0, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 0, 'crewsize_cockpit': 2, 'crewsize_cabin': 3, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'CA                            ', 'ac_subtype_name': 'CAT                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': None, 'alt_reg': None, 'record_id': 25391, 'last_update': '25-OCT-24', 'last_update_user_id': 'iocltm', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "  ... and 18 more errors\n",
      "\n",
      "✓ Disconnected from metadata store\n"
     ]
    }
   ],
   "source": [
    "# Step 5: Create Pydantic Model from Reconstructed Contract\n",
    "print(\"\\n\" + \"=\" * 70)\n",
    "print(\"Step 5: Create Pydantic Model from Reconstructed Contract\")\n",
    "print(\"=\" * 70)\n",
    "\n",
    "# Generate Pydantic model from the reconstructed contract\n",
    "# This will merge coercion and validation rules into the schema\n",
    "AircraftModel = get_model_from_contract(\n",
    "    contract=reconstructed_contract,\n",
    "    model_name=\"Aircraft\"\n",
    ")\n",
    "print(f\"✓ Generated Pydantic model: {AircraftModel.__name__}\")\n",
    "\n",
    "# Test the model with sample data (if available)\n",
    "if df is not None and len(df) > 0:\n",
    "    print(\"\\nTesting model with sample data:\")\n",
    "    sample_data = df.iloc[0].to_dict()\n",
    "    try:\n",
    "        # Clean up the data - handle NaN values and convert datetime objects\n",
    "        cleaned_data = {}\n",
    "        for key, value in sample_data.items():\n",
    "            # Convert column names to lowercase (matching schema property names)\n",
    "            field_name = key.lower() if isinstance(key, str) else key\n",
    "            \n",
    "            if pd.isna(value):\n",
    "                cleaned_data[field_name] = None\n",
    "            elif isinstance(value, pd.Timestamp):\n",
    "                cleaned_data[field_name] = value.isoformat()\n",
    "            elif isinstance(value, (int, float)) and pd.isna(value):\n",
    "                cleaned_data[field_name] = None\n",
    "            else:\n",
    "                cleaned_data[field_name] = value\n",
    "        \n",
    "        # Use the runtime validator to validate and coerce the data\n",
    "        from pycharter import validate_with_contract\n",
    "        \n",
    "        validation_result = validate_with_contract(\n",
    "            data=cleaned_data,\n",
    "            contract=reconstructed_contract\n",
    "        )\n",
    "        \n",
    "        if validation_result.is_valid:\n",
    "            aircraft_instance = AircraftModel(**validation_result.validated_data)\n",
    "            print(f\"✓ Successfully created Aircraft instance\")\n",
    "            print(f\"  Registration: {aircraft_instance.registration}\")\n",
    "            print(f\"  AC Operator: {aircraft_instance.ac_operator}\")\n",
    "            print(f\"  AC Owner: {aircraft_instance.ac_owner}\")\n",
    "        else:\n",
    "            print(f\"⚠ Validation issues found:\")\n",
    "            for error in validation_result.errors[:5]:  # Show first 5 errors\n",
    "                print(f\"  - {error}\")\n",
    "            if len(validation_result.errors) > 5:\n",
    "                print(f\"  ... and {len(validation_result.errors) - 5} more errors\")\n",
    "    except Exception as e:\n",
    "        print(f\"✗ Error creating instance: {e}\")\n",
    "        print(f\"  Error details: {type(e).__name__}\")\n",
    "        import traceback\n",
    "        traceback.print_exc()\n",
    "else:\n",
    "    print(\"\\n⚠ No sample data available for testing\")\n",
    "\n",
    "# Disconnect from store\n",
    "store.disconnect()\n",
    "print(\"\\n✓ Disconnected from metadata store\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "f823fa01-0a15-45a8-8d95-8e576365d5c3",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'$defs': {'AircraftMetadata': {'properties': {},\n",
       "   'title': 'AircraftMetadata',\n",
       "   'type': 'object'}},\n",
       " 'properties': {'metadata': {'$ref': '#/$defs/AircraftMetadata'},\n",
       "  'REGISTRATION': {'description': 'Registration of the Aircraft',\n",
       "   'examples': ['BHNR', 'LD33F'],\n",
       "   'maxLength': 10,\n",
       "   'title': 'Registration',\n",
       "   'type': 'string'},\n",
       "  'VALID_SINCE': {'description': 'Start of validity',\n",
       "   'format': 'date-time',\n",
       "   'title': 'Valid Since',\n",
       "   'type': 'string'},\n",
       "  'VALID_UNTIL': {'description': 'End of validity',\n",
       "   'format': 'date-time',\n",
       "   'title': 'Valid Until',\n",
       "   'type': 'string'},\n",
       "  'AC_OPERATOR': {'description': 'Aircraft Operator',\n",
       "   'examples': ['LD', 'CX'],\n",
       "   'maxLength': 3,\n",
       "   'title': 'Ac Operator',\n",
       "   'type': 'string'},\n",
       "  'AC_OWNER': {'description': 'Owner of the aircraft',\n",
       "   'examples': ['LD', 'CX'],\n",
       "   'maxLength': 3,\n",
       "   'title': 'Ac Owner',\n",
       "   'type': 'string'},\n",
       "  'AC_SUBTYPE': {'description': 'Subtype of the aircraft',\n",
       "   'maxLength': 3,\n",
       "   'title': 'Ac Subtype',\n",
       "   'type': 'string'},\n",
       "  'AC_LOGICAL_NO': {'description': 'Logical number of the Aircraft',\n",
       "   'title': 'Ac Logical No',\n",
       "   'type': 'integer'},\n",
       "  'AC_STATE': {'description': \"Status of Aircraft(''R''=real and ''O''=overflow)\",\n",
       "   'enum': ['R', 'O'],\n",
       "   'maxLength': 1,\n",
       "   'title': 'Ac State',\n",
       "   'type': 'string'},\n",
       "  'DRY_OPERATING_WGT': {'description': 'Dry Operating Weight (kg)',\n",
       "   'title': 'Dry Operating Wgt',\n",
       "   'type': 'integer'},\n",
       "  'MAX_TAKEOFF_WGT': {'description': 'Max Takeoff Weight (kg)',\n",
       "   'title': 'Max Takeoff Wgt',\n",
       "   'type': 'integer'},\n",
       "  'CARGO_CAPACITY': {'description': 'Cargo Capacity (kg)',\n",
       "   'title': 'Cargo Capacity',\n",
       "   'type': 'integer'},\n",
       "  'FUEL_CAPACITY': {'description': 'Fuel Capacity (kg)',\n",
       "   'title': 'Fuel Capacity',\n",
       "   'type': 'integer'},\n",
       "  'AVG_FUEL_CONSUMP': {'description': 'Average Fuel Consumption (kg per hour)',\n",
       "   'title': 'Avg Fuel Consump',\n",
       "   'type': 'integer'},\n",
       "  'AC_INDEX': {'description': 'Aircraft index',\n",
       "   'title': 'Ac Index',\n",
       "   'type': 'integer'},\n",
       "  'CREWSIZE_COCKPIT': {'description': 'Number of Cockpit Crewmembers',\n",
       "   'title': 'Crewsize Cockpit',\n",
       "   'type': 'integer'},\n",
       "  'CREWSIZE_CABIN': {'description': 'Number of Cabin Crewmembers',\n",
       "   'title': 'Crewsize Cabin',\n",
       "   'type': 'integer'},\n",
       "  'STD_VERSION': {'description': 'Aircraft Standard Version',\n",
       "   'maxLength': 20,\n",
       "   'title': 'Std Version',\n",
       "   'type': 'string'},\n",
       "  'AP_RESTRICTION': {'description': \"Airport Restriction - e.g. Political Reason, Performance(''Y'' or ''N'')\",\n",
       "   'examples': ['N', 'Y', 'R'],\n",
       "   'maxLength': 1,\n",
       "   'title': 'Ap Restriction',\n",
       "   'type': 'string'},\n",
       "  'AC_OWNER_NAME': {'description': 'Full Name of Owner',\n",
       "   'maxLength': 30,\n",
       "   'title': 'Ac Owner Name',\n",
       "   'type': 'string'},\n",
       "  'AC_SUBTYPE_NAME': {'description': 'Full Name of Subtype',\n",
       "   'maxLength': 30,\n",
       "   'title': 'Ac Subtype Name',\n",
       "   'type': 'string'},\n",
       "  'AC_CATEGORY': {'description': 'SSIM-Category of Aircraft',\n",
       "   'maxLength': 1,\n",
       "   'title': 'Ac Category',\n",
       "   'type': 'string'},\n",
       "  'REMARK': {'anyOf': [{'type': 'string'}, {'type': 'null'}],\n",
       "   'default': None,\n",
       "   'description': 'Additional remarks',\n",
       "   'title': 'Remark'},\n",
       "  'FUEL_MEASURE_UNIT': {'description': 'Unit for fuel',\n",
       "   'maxLength': 3,\n",
       "   'title': 'Fuel Measure Unit',\n",
       "   'type': 'string'},\n",
       "  'AC_CALLSIGN': {'anyOf': [{'type': 'string'}, {'type': 'null'}],\n",
       "   'default': None,\n",
       "   'description': 'Callsign of aircraft',\n",
       "   'title': 'Ac Callsign'},\n",
       "  'RADIO': {'anyOf': [{'type': 'string'}, {'type': 'null'}],\n",
       "   'default': None,\n",
       "   'description': 'Radio type',\n",
       "   'title': 'Radio'},\n",
       "  'NOISE': {'anyOf': [{'type': 'string'}, {'type': 'null'}],\n",
       "   'default': None,\n",
       "   'description': 'ICAO noise chapter',\n",
       "   'title': 'Noise'},\n",
       "  'PHONE': {'anyOf': [{'type': 'string'}, {'type': 'null'}],\n",
       "   'default': None,\n",
       "   'description': 'Onboard mobile phone number',\n",
       "   'title': 'Phone'},\n",
       "  'SPECIAL_EQUIPMENT': {'anyOf': [{'type': 'string'}, {'type': 'null'}],\n",
       "   'default': None,\n",
       "   'description': 'Special equipment',\n",
       "   'title': 'Special Equipment'},\n",
       "  'ACARS': {'anyOf': [{'enum': ['V', 'H', 'S'], 'type': 'string'},\n",
       "    {'type': 'null'}],\n",
       "   'default': None,\n",
       "   'description': 'ACARS type',\n",
       "   'enum': ['V', 'H', 'S'],\n",
       "   'title': 'Acars'},\n",
       "  'ALT_REG': {'anyOf': [{'type': 'string'}, {'type': 'null'}],\n",
       "   'default': None,\n",
       "   'description': 'Alternate Registration',\n",
       "   'title': 'Alt Reg'},\n",
       "  'RECORD_ID': {'anyOf': [{'type': 'integer'}, {'type': 'null'}],\n",
       "   'default': 0,\n",
       "   'description': 'Record ID',\n",
       "   'title': 'Record Id'},\n",
       "  'LAST_UPDATE': {'anyOf': [{'type': 'string'}, {'type': 'null'}],\n",
       "   'default': None,\n",
       "   'description': 'Timestamp of last update',\n",
       "   'title': 'Last Update'},\n",
       "  'LAST_UPDATE_USER_ID': {'anyOf': [{'type': 'string'}, {'type': 'null'}],\n",
       "   'default': None,\n",
       "   'description': 'User ID of last update',\n",
       "   'title': 'Last Update User Id'},\n",
       "  'STD_VERSION_ALT_1': {'anyOf': [{'type': 'string'}, {'type': 'null'}],\n",
       "   'default': None,\n",
       "   'description': 'Alternative Aircraft Version 1',\n",
       "   'title': 'Std Version Alt 1'},\n",
       "  'STD_VERSION_ALT_2': {'anyOf': [{'type': 'string'}, {'type': 'null'}],\n",
       "   'default': None,\n",
       "   'description': 'Alternative Aircraft Version 2',\n",
       "   'title': 'Std Version Alt 2'},\n",
       "  'STD_VERSION_ALT_3': {'anyOf': [{'type': 'string'}, {'type': 'null'}],\n",
       "   'default': None,\n",
       "   'description': 'Alternative Aircraft Version 3',\n",
       "   'title': 'Std Version Alt 3'},\n",
       "  'STD_VERSION_ALT_4': {'anyOf': [{'type': 'string'}, {'type': 'null'}],\n",
       "   'default': None,\n",
       "   'description': 'Alternative Aircraft Version 4',\n",
       "   'title': 'Std Version Alt 4'},\n",
       "  'ILS_EQUIPMENT': {'anyOf': [{'enum': ['I', 'II', 'IIIa', 'IIIb'],\n",
       "     'maxLength': 4,\n",
       "     'type': 'string'},\n",
       "    {'type': 'null'}],\n",
       "   'default': 'I',\n",
       "   'description': 'aircraft equipment supporting ILS CAT approaches(I, II, IIIa, IIIb)',\n",
       "   'enum': ['I', 'II', 'IIIa', 'IIIb'],\n",
       "   'title': 'Ils Equipment'},\n",
       "  'AUTOLAND': {'anyOf': [{'enum': ['Y', 'N'],\n",
       "     'maxLength': 1,\n",
       "     'type': 'string'},\n",
       "    {'type': 'null'}],\n",
       "   'default': 'N',\n",
       "   'description': 'Autoland capability indicator',\n",
       "   'enum': ['Y', 'N'],\n",
       "   'title': 'Autoland'},\n",
       "  'HOMEBASE': {'anyOf': [{'type': 'string'}, {'type': 'null'}],\n",
       "   'default': None,\n",
       "   'description': 'Homebase of the aircraft (IATA CODE)',\n",
       "   'title': 'Homebase'}},\n",
       " 'required': ['metadata',\n",
       "  'REGISTRATION',\n",
       "  'VALID_SINCE',\n",
       "  'VALID_UNTIL',\n",
       "  'AC_OPERATOR',\n",
       "  'AC_OWNER',\n",
       "  'AC_SUBTYPE',\n",
       "  'AC_LOGICAL_NO',\n",
       "  'AC_STATE',\n",
       "  'DRY_OPERATING_WGT',\n",
       "  'MAX_TAKEOFF_WGT',\n",
       "  'CARGO_CAPACITY',\n",
       "  'FUEL_CAPACITY',\n",
       "  'AVG_FUEL_CONSUMP',\n",
       "  'AC_INDEX',\n",
       "  'CREWSIZE_COCKPIT',\n",
       "  'CREWSIZE_CABIN',\n",
       "  'STD_VERSION',\n",
       "  'AP_RESTRICTION',\n",
       "  'AC_OWNER_NAME',\n",
       "  'AC_SUBTYPE_NAME',\n",
       "  'AC_CATEGORY',\n",
       "  'FUEL_MEASURE_UNIT'],\n",
       " 'title': 'Aircraft',\n",
       " 'type': 'object'}"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "AircraftModel.model_json_schema()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "533e3e8f-b10b-4518-a83e-4544e91cb9ee",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['__abstractmethods__',\n",
       " '__annotations__',\n",
       " '__class__',\n",
       " '__class_getitem__',\n",
       " '__class_vars__',\n",
       " '__copy__',\n",
       " '__deepcopy__',\n",
       " '__delattr__',\n",
       " '__dict__',\n",
       " '__dir__',\n",
       " '__doc__',\n",
       " '__eq__',\n",
       " '__fields_set__',\n",
       " '__format__',\n",
       " '__ge__',\n",
       " '__get_pydantic_core_schema__',\n",
       " '__get_pydantic_json_schema__',\n",
       " '__getattr__',\n",
       " '__getattribute__',\n",
       " '__getstate__',\n",
       " '__gt__',\n",
       " '__hash__',\n",
       " '__init__',\n",
       " '__init_subclass__',\n",
       " '__iter__',\n",
       " '__le__',\n",
       " '__lt__',\n",
       " '__module__',\n",
       " '__ne__',\n",
       " '__new__',\n",
       " '__pretty__',\n",
       " '__private_attributes__',\n",
       " '__pydantic_complete__',\n",
       " '__pydantic_computed_fields__',\n",
       " '__pydantic_core_schema__',\n",
       " '__pydantic_custom_init__',\n",
       " '__pydantic_decorators__',\n",
       " '__pydantic_extra__',\n",
       " '__pydantic_fields__',\n",
       " '__pydantic_fields_set__',\n",
       " '__pydantic_generic_metadata__',\n",
       " '__pydantic_init_subclass__',\n",
       " '__pydantic_on_complete__',\n",
       " '__pydantic_parent_namespace__',\n",
       " '__pydantic_post_init__',\n",
       " '__pydantic_private__',\n",
       " '__pydantic_root_model__',\n",
       " '__pydantic_serializer__',\n",
       " '__pydantic_setattr_handlers__',\n",
       " '__pydantic_validator__',\n",
       " '__reduce__',\n",
       " '__reduce_ex__',\n",
       " '__replace__',\n",
       " '__repr__',\n",
       " '__repr_args__',\n",
       " '__repr_name__',\n",
       " '__repr_recursion__',\n",
       " '__repr_str__',\n",
       " '__rich_repr__',\n",
       " '__setattr__',\n",
       " '__setstate__',\n",
       " '__signature__',\n",
       " '__sizeof__',\n",
       " '__slots__',\n",
       " '__str__',\n",
       " '__subclasshook__',\n",
       " '__weakref__',\n",
       " '_abc_impl',\n",
       " '_calculate_keys',\n",
       " '_coerce_ACARS',\n",
       " '_coerce_AC_CALLSIGN',\n",
       " '_coerce_AC_CATEGORY',\n",
       " '_coerce_AC_INDEX',\n",
       " '_coerce_AC_LOGICAL_NO',\n",
       " '_coerce_AC_OPERATOR',\n",
       " '_coerce_AC_OWNER',\n",
       " '_coerce_AC_OWNER_NAME',\n",
       " '_coerce_AC_STATE',\n",
       " '_coerce_AC_SUBTYPE',\n",
       " '_coerce_AC_SUBTYPE_NAME',\n",
       " '_coerce_ALT_REG',\n",
       " '_coerce_AP_RESTRICTION',\n",
       " '_coerce_AUTOLAND',\n",
       " '_coerce_AVG_FUEL_CONSUMP',\n",
       " '_coerce_CARGO_CAPACITY',\n",
       " '_coerce_CREWSIZE_CABIN',\n",
       " '_coerce_CREWSIZE_COCKPIT',\n",
       " '_coerce_DRY_OPERATING_WGT',\n",
       " '_coerce_FUEL_CAPACITY',\n",
       " '_coerce_FUEL_MEASURE_UNIT',\n",
       " '_coerce_HOMEBASE',\n",
       " '_coerce_ILS_EQUIPMENT',\n",
       " '_coerce_LAST_UPDATE',\n",
       " '_coerce_LAST_UPDATE_USER_ID',\n",
       " '_coerce_MAX_TAKEOFF_WGT',\n",
       " '_coerce_NOISE',\n",
       " '_coerce_PHONE',\n",
       " '_coerce_RADIO',\n",
       " '_coerce_RECORD_ID',\n",
       " '_coerce_REGISTRATION',\n",
       " '_coerce_REMARK',\n",
       " '_coerce_SPECIAL_EQUIPMENT',\n",
       " '_coerce_STD_VERSION',\n",
       " '_coerce_STD_VERSION_ALT_1',\n",
       " '_coerce_STD_VERSION_ALT_2',\n",
       " '_coerce_STD_VERSION_ALT_3',\n",
       " '_coerce_STD_VERSION_ALT_4',\n",
       " '_coerce_VALID_SINCE',\n",
       " '_coerce_VALID_UNTIL',\n",
       " '_copy_and_set_values',\n",
       " '_get_value',\n",
       " '_iter',\n",
       " '_setattr_handler',\n",
       " '_validate_ACARS_0',\n",
       " '_validate_ACARS_1',\n",
       " '_validate_AC_CALLSIGN_0',\n",
       " '_validate_AC_CATEGORY_0',\n",
       " '_validate_AC_CATEGORY_1',\n",
       " '_validate_AC_OPERATOR_0',\n",
       " '_validate_AC_OPERATOR_1',\n",
       " '_validate_AC_OWNER_0',\n",
       " '_validate_AC_OWNER_1',\n",
       " '_validate_AC_OWNER_NAME_0',\n",
       " '_validate_AC_OWNER_NAME_1',\n",
       " '_validate_AC_STATE_0',\n",
       " '_validate_AC_STATE_1',\n",
       " '_validate_AC_SUBTYPE_0',\n",
       " '_validate_AC_SUBTYPE_1',\n",
       " '_validate_AC_SUBTYPE_NAME_0',\n",
       " '_validate_AC_SUBTYPE_NAME_1',\n",
       " '_validate_ALT_REG_0',\n",
       " '_validate_AP_RESTRICTION_0',\n",
       " '_validate_AP_RESTRICTION_1',\n",
       " '_validate_AUTOLAND_0',\n",
       " '_validate_AUTOLAND_1',\n",
       " '_validate_AVG_FUEL_CONSUMP_0',\n",
       " '_validate_CARGO_CAPACITY_0',\n",
       " '_validate_CREWSIZE_CABIN_0',\n",
       " '_validate_CREWSIZE_COCKPIT_0',\n",
       " '_validate_DRY_OPERATING_WGT_0',\n",
       " '_validate_FUEL_CAPACITY_0',\n",
       " '_validate_FUEL_MEASURE_UNIT_0',\n",
       " '_validate_FUEL_MEASURE_UNIT_1',\n",
       " '_validate_HOMEBASE_0',\n",
       " '_validate_ILS_EQUIPMENT_0',\n",
       " '_validate_ILS_EQUIPMENT_1',\n",
       " '_validate_LAST_UPDATE_USER_ID_0',\n",
       " '_validate_MAX_TAKEOFF_WGT_0',\n",
       " '_validate_NOISE_0',\n",
       " '_validate_PHONE_0',\n",
       " '_validate_RADIO_0',\n",
       " '_validate_REGISTRATION_0',\n",
       " '_validate_REGISTRATION_1',\n",
       " '_validate_REMARK_0',\n",
       " '_validate_SPECIAL_EQUIPMENT_0',\n",
       " '_validate_STD_VERSION_0',\n",
       " '_validate_STD_VERSION_1',\n",
       " '_validate_STD_VERSION_ALT_1_0',\n",
       " '_validate_STD_VERSION_ALT_2_0',\n",
       " '_validate_STD_VERSION_ALT_3_0',\n",
       " '_validate_STD_VERSION_ALT_4_0',\n",
       " 'construct',\n",
       " 'copy',\n",
       " 'dict',\n",
       " 'from_orm',\n",
       " 'json',\n",
       " 'model_computed_fields',\n",
       " 'model_config',\n",
       " 'model_construct',\n",
       " 'model_copy',\n",
       " 'model_dump',\n",
       " 'model_dump_json',\n",
       " 'model_extra',\n",
       " 'model_fields',\n",
       " 'model_fields_set',\n",
       " 'model_json_schema',\n",
       " 'model_parametrized_name',\n",
       " 'model_post_init',\n",
       " 'model_rebuild',\n",
       " 'model_validate',\n",
       " 'model_validate_json',\n",
       " 'model_validate_strings',\n",
       " 'parse_file',\n",
       " 'parse_obj',\n",
       " 'parse_raw',\n",
       " 'schema',\n",
       " 'schema_json',\n",
       " 'update_forward_refs',\n",
       " 'validate']"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dir(AircraftModel)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "32247b5e-4eab-4cf0-87a1-b546eb3fbbae",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'01-OCT-19'"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.iloc[0]['VALID_UNTIL']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "520633c8-d011-44c9-931d-6fe0a3b2e7b6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "datetime.datetime(2019, 10, 1, 0, 0)"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "AircraftModel._coerce_VALID_SINCE(df.iloc[0]['VALID_UNTIL'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "dcfc6087-baa8-4a1c-a733-75c36cca9fa9",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "======================================================================\n",
      "Step 6: Batch Validation with Multiple Records\n",
      "======================================================================\n",
      "\n",
      "Preparing 10 records for batch validation...\n",
      "✓ Prepared 10 records for validation\n",
      "\n",
      "Validating batch of 10 records...\n",
      "✓ Batch validation completed in 0.036 seconds\n",
      "\n",
      "Validation Summary:\n",
      "  Total records: 10\n",
      "  Valid records: 0 (0.0%)\n",
      "  Invalid records: 10 (100.0%)\n",
      "  Average time per record: 3.57 ms\n",
      "\n",
      "Invalid Records Details:\n",
      "\n",
      "  Record 1:\n",
      "    Errors: 23\n",
      "      - {'type': 'missing', 'loc': ('metadata',), 'msg': 'Field required', 'input': {'registration': 'CACAT', 'valid_since': '01-JAN-14', 'valid_until': '01-OCT-19', 'ac_operator': 'CA ', 'ac_owner': 'CA', 'ac_subtype': 'CAT', 'ac_logical_no': 0, 'ac_state': 'O', 'dry_operating_wgt': 0, 'max_takeoff_wgt': 0, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 0, 'crewsize_cockpit': 2, 'crewsize_cabin': 3, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'CA                            ', 'ac_subtype_name': 'CAT                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': None, 'alt_reg': None, 'record_id': 25391, 'last_update': '25-OCT-24', 'last_update_user_id': 'iocltm', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      - {'type': 'missing', 'loc': ('REGISTRATION',), 'msg': 'Field required', 'input': {'registration': 'CACAT', 'valid_since': '01-JAN-14', 'valid_until': '01-OCT-19', 'ac_operator': 'CA ', 'ac_owner': 'CA', 'ac_subtype': 'CAT', 'ac_logical_no': 0, 'ac_state': 'O', 'dry_operating_wgt': 0, 'max_takeoff_wgt': 0, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 0, 'crewsize_cockpit': 2, 'crewsize_cabin': 3, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'CA                            ', 'ac_subtype_name': 'CAT                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': None, 'alt_reg': None, 'record_id': 25391, 'last_update': '25-OCT-24', 'last_update_user_id': 'iocltm', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      - {'type': 'missing', 'loc': ('VALID_SINCE',), 'msg': 'Field required', 'input': {'registration': 'CACAT', 'valid_since': '01-JAN-14', 'valid_until': '01-OCT-19', 'ac_operator': 'CA ', 'ac_owner': 'CA', 'ac_subtype': 'CAT', 'ac_logical_no': 0, 'ac_state': 'O', 'dry_operating_wgt': 0, 'max_takeoff_wgt': 0, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 0, 'crewsize_cockpit': 2, 'crewsize_cabin': 3, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'CA                            ', 'ac_subtype_name': 'CAT                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': None, 'alt_reg': None, 'record_id': 25391, 'last_update': '25-OCT-24', 'last_update_user_id': 'iocltm', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      ... and 20 more errors\n",
      "\n",
      "  Record 2:\n",
      "    Errors: 23\n",
      "      - {'type': 'missing', 'loc': ('metadata',), 'msg': 'Field required', 'input': {'registration': 'CACAU', 'valid_since': '01-JAN-14', 'valid_until': '01-OCT-19', 'ac_operator': 'CA ', 'ac_owner': 'CA', 'ac_subtype': 'CAU', 'ac_logical_no': 0, 'ac_state': 'O', 'dry_operating_wgt': 0, 'max_takeoff_wgt': 0, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 0, 'crewsize_cockpit': 2, 'crewsize_cabin': 3, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'CA                            ', 'ac_subtype_name': 'CAU                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': None, 'alt_reg': None, 'record_id': 25392, 'last_update': '25-OCT-24', 'last_update_user_id': 'iocltm', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      - {'type': 'missing', 'loc': ('REGISTRATION',), 'msg': 'Field required', 'input': {'registration': 'CACAU', 'valid_since': '01-JAN-14', 'valid_until': '01-OCT-19', 'ac_operator': 'CA ', 'ac_owner': 'CA', 'ac_subtype': 'CAU', 'ac_logical_no': 0, 'ac_state': 'O', 'dry_operating_wgt': 0, 'max_takeoff_wgt': 0, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 0, 'crewsize_cockpit': 2, 'crewsize_cabin': 3, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'CA                            ', 'ac_subtype_name': 'CAU                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': None, 'alt_reg': None, 'record_id': 25392, 'last_update': '25-OCT-24', 'last_update_user_id': 'iocltm', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      - {'type': 'missing', 'loc': ('VALID_SINCE',), 'msg': 'Field required', 'input': {'registration': 'CACAU', 'valid_since': '01-JAN-14', 'valid_until': '01-OCT-19', 'ac_operator': 'CA ', 'ac_owner': 'CA', 'ac_subtype': 'CAU', 'ac_logical_no': 0, 'ac_state': 'O', 'dry_operating_wgt': 0, 'max_takeoff_wgt': 0, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 0, 'crewsize_cockpit': 2, 'crewsize_cabin': 3, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'CA                            ', 'ac_subtype_name': 'CAU                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': None, 'alt_reg': None, 'record_id': 25392, 'last_update': '25-OCT-24', 'last_update_user_id': 'iocltm', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      ... and 20 more errors\n",
      "\n",
      "  Record 3:\n",
      "    Errors: 23\n",
      "      - {'type': 'missing', 'loc': ('metadata',), 'msg': 'Field required', 'input': {'registration': 'CACAV', 'valid_since': '01-JAN-14', 'valid_until': '01-OCT-19', 'ac_operator': 'CA ', 'ac_owner': 'CA', 'ac_subtype': 'CAV', 'ac_logical_no': 0, 'ac_state': 'O', 'dry_operating_wgt': 0, 'max_takeoff_wgt': 0, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 0, 'crewsize_cockpit': 2, 'crewsize_cabin': 3, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'CA                            ', 'ac_subtype_name': 'CAV                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': None, 'alt_reg': None, 'record_id': 25393, 'last_update': '25-OCT-24', 'last_update_user_id': 'iocltm', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      - {'type': 'missing', 'loc': ('REGISTRATION',), 'msg': 'Field required', 'input': {'registration': 'CACAV', 'valid_since': '01-JAN-14', 'valid_until': '01-OCT-19', 'ac_operator': 'CA ', 'ac_owner': 'CA', 'ac_subtype': 'CAV', 'ac_logical_no': 0, 'ac_state': 'O', 'dry_operating_wgt': 0, 'max_takeoff_wgt': 0, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 0, 'crewsize_cockpit': 2, 'crewsize_cabin': 3, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'CA                            ', 'ac_subtype_name': 'CAV                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': None, 'alt_reg': None, 'record_id': 25393, 'last_update': '25-OCT-24', 'last_update_user_id': 'iocltm', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      - {'type': 'missing', 'loc': ('VALID_SINCE',), 'msg': 'Field required', 'input': {'registration': 'CACAV', 'valid_since': '01-JAN-14', 'valid_until': '01-OCT-19', 'ac_operator': 'CA ', 'ac_owner': 'CA', 'ac_subtype': 'CAV', 'ac_logical_no': 0, 'ac_state': 'O', 'dry_operating_wgt': 0, 'max_takeoff_wgt': 0, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 0, 'crewsize_cockpit': 2, 'crewsize_cabin': 3, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'CA                            ', 'ac_subtype_name': 'CAV                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': None, 'alt_reg': None, 'record_id': 25393, 'last_update': '25-OCT-24', 'last_update_user_id': 'iocltm', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      ... and 20 more errors\n",
      "\n",
      "  Record 4:\n",
      "    Errors: 23\n",
      "      - {'type': 'missing', 'loc': ('metadata',), 'msg': 'Field required', 'input': {'registration': 'BHSQ', 'valid_since': '05-DEC-16', 'valid_until': '23-FEB-22', 'ac_operator': 'KA ', 'ac_owner': 'KA', 'ac_subtype': '320', 'ac_logical_no': 12, 'ac_state': 'R', 'dry_operating_wgt': 44088, 'max_takeoff_wgt': 75500, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 300, 'crewsize_cockpit': 0, 'crewsize_cabin': 0, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'KA                            ', 'ac_subtype_name': '320                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': 'V', 'alt_reg': None, 'record_id': 267280, 'last_update': '02-MAR-22', 'last_update_user_id': 'netline', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      - {'type': 'missing', 'loc': ('REGISTRATION',), 'msg': 'Field required', 'input': {'registration': 'BHSQ', 'valid_since': '05-DEC-16', 'valid_until': '23-FEB-22', 'ac_operator': 'KA ', 'ac_owner': 'KA', 'ac_subtype': '320', 'ac_logical_no': 12, 'ac_state': 'R', 'dry_operating_wgt': 44088, 'max_takeoff_wgt': 75500, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 300, 'crewsize_cockpit': 0, 'crewsize_cabin': 0, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'KA                            ', 'ac_subtype_name': '320                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': 'V', 'alt_reg': None, 'record_id': 267280, 'last_update': '02-MAR-22', 'last_update_user_id': 'netline', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      - {'type': 'missing', 'loc': ('VALID_SINCE',), 'msg': 'Field required', 'input': {'registration': 'BHSQ', 'valid_since': '05-DEC-16', 'valid_until': '23-FEB-22', 'ac_operator': 'KA ', 'ac_owner': 'KA', 'ac_subtype': '320', 'ac_logical_no': 12, 'ac_state': 'R', 'dry_operating_wgt': 44088, 'max_takeoff_wgt': 75500, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 300, 'crewsize_cockpit': 0, 'crewsize_cabin': 0, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'KA                            ', 'ac_subtype_name': '320                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': 'V', 'alt_reg': None, 'record_id': 267280, 'last_update': '02-MAR-22', 'last_update_user_id': 'netline', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      ... and 20 more errors\n",
      "\n",
      "  Record 5:\n",
      "    Errors: 23\n",
      "      - {'type': 'missing', 'loc': ('metadata',), 'msg': 'Field required', 'input': {'registration': 'KA32M', 'valid_since': '01-JAN-12', 'valid_until': '31-DEC-13', 'ac_operator': 'KA ', 'ac_owner': 'KA', 'ac_subtype': '32M', 'ac_logical_no': 0, 'ac_state': 'O', 'dry_operating_wgt': 0, 'max_takeoff_wgt': 0, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 310, 'crewsize_cockpit': 0, 'crewsize_cabin': 0, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'KA                            ', 'ac_subtype_name': '32M                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': None, 'alt_reg': None, 'record_id': 25395, 'last_update': '02-MAR-22', 'last_update_user_id': 'netline', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      - {'type': 'missing', 'loc': ('REGISTRATION',), 'msg': 'Field required', 'input': {'registration': 'KA32M', 'valid_since': '01-JAN-12', 'valid_until': '31-DEC-13', 'ac_operator': 'KA ', 'ac_owner': 'KA', 'ac_subtype': '32M', 'ac_logical_no': 0, 'ac_state': 'O', 'dry_operating_wgt': 0, 'max_takeoff_wgt': 0, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 310, 'crewsize_cockpit': 0, 'crewsize_cabin': 0, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'KA                            ', 'ac_subtype_name': '32M                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': None, 'alt_reg': None, 'record_id': 25395, 'last_update': '02-MAR-22', 'last_update_user_id': 'netline', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      - {'type': 'missing', 'loc': ('VALID_SINCE',), 'msg': 'Field required', 'input': {'registration': 'KA32M', 'valid_since': '01-JAN-12', 'valid_until': '31-DEC-13', 'ac_operator': 'KA ', 'ac_owner': 'KA', 'ac_subtype': '32M', 'ac_logical_no': 0, 'ac_state': 'O', 'dry_operating_wgt': 0, 'max_takeoff_wgt': 0, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 310, 'crewsize_cockpit': 0, 'crewsize_cabin': 0, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'KA                            ', 'ac_subtype_name': '32M                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': None, 'alt_reg': None, 'record_id': 25395, 'last_update': '02-MAR-22', 'last_update_user_id': 'netline', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      ... and 20 more errors\n",
      "\n",
      "  Record 6:\n",
      "    Errors: 23\n",
      "      - {'type': 'missing', 'loc': ('metadata',), 'msg': 'Field required', 'input': {'registration': 'BLAI', 'valid_since': '30-NOV-14', 'valid_until': '31-DEC-14', 'ac_operator': 'CX ', 'ac_owner': 'CX', 'ac_subtype': '33K', 'ac_logical_no': 13, 'ac_state': 'R', 'dry_operating_wgt': 124887, 'max_takeoff_wgt': 233000, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 70, 'crewsize_cockpit': 0, 'crewsize_cabin': 0, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'CATHAY PACIFIC                ', 'ac_subtype_name': '33K                           ', 'ac_category': 'J', 'remark': '39J/21W/191Y = 251  / TRNG FLT RESTRICTION DUE ADDITIONAL RENT FOR EXCESS CYCLES', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': 'S', 'alt_reg': None, 'record_id': 57420, 'last_update': '02-MAR-22', 'last_update_user_id': 'netline', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      - {'type': 'missing', 'loc': ('REGISTRATION',), 'msg': 'Field required', 'input': {'registration': 'BLAI', 'valid_since': '30-NOV-14', 'valid_until': '31-DEC-14', 'ac_operator': 'CX ', 'ac_owner': 'CX', 'ac_subtype': '33K', 'ac_logical_no': 13, 'ac_state': 'R', 'dry_operating_wgt': 124887, 'max_takeoff_wgt': 233000, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 70, 'crewsize_cockpit': 0, 'crewsize_cabin': 0, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'CATHAY PACIFIC                ', 'ac_subtype_name': '33K                           ', 'ac_category': 'J', 'remark': '39J/21W/191Y = 251  / TRNG FLT RESTRICTION DUE ADDITIONAL RENT FOR EXCESS CYCLES', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': 'S', 'alt_reg': None, 'record_id': 57420, 'last_update': '02-MAR-22', 'last_update_user_id': 'netline', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      - {'type': 'missing', 'loc': ('VALID_SINCE',), 'msg': 'Field required', 'input': {'registration': 'BLAI', 'valid_since': '30-NOV-14', 'valid_until': '31-DEC-14', 'ac_operator': 'CX ', 'ac_owner': 'CX', 'ac_subtype': '33K', 'ac_logical_no': 13, 'ac_state': 'R', 'dry_operating_wgt': 124887, 'max_takeoff_wgt': 233000, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 70, 'crewsize_cockpit': 0, 'crewsize_cabin': 0, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'CATHAY PACIFIC                ', 'ac_subtype_name': '33K                           ', 'ac_category': 'J', 'remark': '39J/21W/191Y = 251  / TRNG FLT RESTRICTION DUE ADDITIONAL RENT FOR EXCESS CYCLES', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': 'S', 'alt_reg': None, 'record_id': 57420, 'last_update': '02-MAR-22', 'last_update_user_id': 'netline', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      ... and 20 more errors\n",
      "\n",
      "  Record 7:\n",
      "    Errors: 23\n",
      "      - {'type': 'missing', 'loc': ('metadata',), 'msg': 'Field required', 'input': {'registration': 'CX74N', 'valid_since': '01-JAN-10', 'valid_until': '31-DEC-35', 'ac_operator': 'CX ', 'ac_owner': 'CX', 'ac_subtype': '74N', 'ac_logical_no': 0, 'ac_state': 'O', 'dry_operating_wgt': 0, 'max_takeoff_wgt': 0, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 210, 'crewsize_cockpit': 0, 'crewsize_cabin': 0, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'CX                            ', 'ac_subtype_name': '74N                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': None, 'alt_reg': None, 'record_id': 25397, 'last_update': '02-MAR-22', 'last_update_user_id': 'netline', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      - {'type': 'missing', 'loc': ('REGISTRATION',), 'msg': 'Field required', 'input': {'registration': 'CX74N', 'valid_since': '01-JAN-10', 'valid_until': '31-DEC-35', 'ac_operator': 'CX ', 'ac_owner': 'CX', 'ac_subtype': '74N', 'ac_logical_no': 0, 'ac_state': 'O', 'dry_operating_wgt': 0, 'max_takeoff_wgt': 0, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 210, 'crewsize_cockpit': 0, 'crewsize_cabin': 0, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'CX                            ', 'ac_subtype_name': '74N                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': None, 'alt_reg': None, 'record_id': 25397, 'last_update': '02-MAR-22', 'last_update_user_id': 'netline', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      - {'type': 'missing', 'loc': ('VALID_SINCE',), 'msg': 'Field required', 'input': {'registration': 'CX74N', 'valid_since': '01-JAN-10', 'valid_until': '31-DEC-35', 'ac_operator': 'CX ', 'ac_owner': 'CX', 'ac_subtype': '74N', 'ac_logical_no': 0, 'ac_state': 'O', 'dry_operating_wgt': 0, 'max_takeoff_wgt': 0, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 210, 'crewsize_cockpit': 0, 'crewsize_cabin': 0, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'CX                            ', 'ac_subtype_name': '74N                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': None, 'alt_reg': None, 'record_id': 25397, 'last_update': '02-MAR-22', 'last_update_user_id': 'netline', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      ... and 20 more errors\n",
      "\n",
      "  Record 8:\n",
      "    Errors: 23\n",
      "      - {'type': 'missing', 'loc': ('metadata',), 'msg': 'Field required', 'input': {'registration': 'CACA6', 'valid_since': '01-JAN-08', 'valid_until': '01-OCT-19', 'ac_operator': 'CA ', 'ac_owner': 'CA', 'ac_subtype': 'CA6', 'ac_logical_no': 0, 'ac_state': 'O', 'dry_operating_wgt': 0, 'max_takeoff_wgt': 0, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 0, 'crewsize_cockpit': 2, 'crewsize_cabin': 3, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'CA                            ', 'ac_subtype_name': 'CA6                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': None, 'alt_reg': None, 'record_id': 25398, 'last_update': '25-OCT-24', 'last_update_user_id': 'iocltm', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      - {'type': 'missing', 'loc': ('REGISTRATION',), 'msg': 'Field required', 'input': {'registration': 'CACA6', 'valid_since': '01-JAN-08', 'valid_until': '01-OCT-19', 'ac_operator': 'CA ', 'ac_owner': 'CA', 'ac_subtype': 'CA6', 'ac_logical_no': 0, 'ac_state': 'O', 'dry_operating_wgt': 0, 'max_takeoff_wgt': 0, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 0, 'crewsize_cockpit': 2, 'crewsize_cabin': 3, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'CA                            ', 'ac_subtype_name': 'CA6                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': None, 'alt_reg': None, 'record_id': 25398, 'last_update': '25-OCT-24', 'last_update_user_id': 'iocltm', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      - {'type': 'missing', 'loc': ('VALID_SINCE',), 'msg': 'Field required', 'input': {'registration': 'CACA6', 'valid_since': '01-JAN-08', 'valid_until': '01-OCT-19', 'ac_operator': 'CA ', 'ac_owner': 'CA', 'ac_subtype': 'CA6', 'ac_logical_no': 0, 'ac_state': 'O', 'dry_operating_wgt': 0, 'max_takeoff_wgt': 0, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 0, 'crewsize_cockpit': 2, 'crewsize_cabin': 3, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'CA                            ', 'ac_subtype_name': 'CA6                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': None, 'alt_reg': None, 'record_id': 25398, 'last_update': '25-OCT-24', 'last_update_user_id': 'iocltm', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      ... and 20 more errors\n",
      "\n",
      "  Record 9:\n",
      "    Errors: 23\n",
      "      - {'type': 'missing', 'loc': ('metadata',), 'msg': 'Field required', 'input': {'registration': 'BHSR', 'valid_since': '02-JAN-17', 'valid_until': '10-JAN-22', 'ac_operator': 'KA ', 'ac_owner': 'KA', 'ac_subtype': '320', 'ac_logical_no': 13, 'ac_state': 'R', 'dry_operating_wgt': 44088, 'max_takeoff_wgt': 75500, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 300, 'crewsize_cockpit': 0, 'crewsize_cabin': 0, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'KA                            ', 'ac_subtype_name': '320                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': 'V', 'alt_reg': None, 'record_id': 267281, 'last_update': '02-MAR-22', 'last_update_user_id': 'netline', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      - {'type': 'missing', 'loc': ('REGISTRATION',), 'msg': 'Field required', 'input': {'registration': 'BHSR', 'valid_since': '02-JAN-17', 'valid_until': '10-JAN-22', 'ac_operator': 'KA ', 'ac_owner': 'KA', 'ac_subtype': '320', 'ac_logical_no': 13, 'ac_state': 'R', 'dry_operating_wgt': 44088, 'max_takeoff_wgt': 75500, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 300, 'crewsize_cockpit': 0, 'crewsize_cabin': 0, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'KA                            ', 'ac_subtype_name': '320                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': 'V', 'alt_reg': None, 'record_id': 267281, 'last_update': '02-MAR-22', 'last_update_user_id': 'netline', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      - {'type': 'missing', 'loc': ('VALID_SINCE',), 'msg': 'Field required', 'input': {'registration': 'BHSR', 'valid_since': '02-JAN-17', 'valid_until': '10-JAN-22', 'ac_operator': 'KA ', 'ac_owner': 'KA', 'ac_subtype': '320', 'ac_logical_no': 13, 'ac_state': 'R', 'dry_operating_wgt': 44088, 'max_takeoff_wgt': 75500, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 300, 'crewsize_cockpit': 0, 'crewsize_cabin': 0, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'KA                            ', 'ac_subtype_name': '320                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': 'V', 'alt_reg': None, 'record_id': 267281, 'last_update': '02-MAR-22', 'last_update_user_id': 'netline', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      ... and 20 more errors\n",
      "\n",
      "  Record 10:\n",
      "    Errors: 23\n",
      "      - {'type': 'missing', 'loc': ('metadata',), 'msg': 'Field required', 'input': {'registration': 'BHUR', 'valid_since': '27-JUL-17', 'valid_until': '31-AUG-18', 'ac_operator': 'CX ', 'ac_owner': 'CX', 'ac_subtype': '7CF', 'ac_logical_no': 3, 'ac_state': 'R', 'dry_operating_wgt': 1, 'max_takeoff_wgt': 1, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 190, 'crewsize_cockpit': 0, 'crewsize_cabin': 0, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'CX                            ', 'ac_subtype_name': '7CF                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': 'S', 'alt_reg': None, 'record_id': 309080, 'last_update': '02-MAR-22', 'last_update_user_id': 'netline', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      - {'type': 'missing', 'loc': ('REGISTRATION',), 'msg': 'Field required', 'input': {'registration': 'BHUR', 'valid_since': '27-JUL-17', 'valid_until': '31-AUG-18', 'ac_operator': 'CX ', 'ac_owner': 'CX', 'ac_subtype': '7CF', 'ac_logical_no': 3, 'ac_state': 'R', 'dry_operating_wgt': 1, 'max_takeoff_wgt': 1, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 190, 'crewsize_cockpit': 0, 'crewsize_cabin': 0, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'CX                            ', 'ac_subtype_name': '7CF                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': 'S', 'alt_reg': None, 'record_id': 309080, 'last_update': '02-MAR-22', 'last_update_user_id': 'netline', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      - {'type': 'missing', 'loc': ('VALID_SINCE',), 'msg': 'Field required', 'input': {'registration': 'BHUR', 'valid_since': '27-JUL-17', 'valid_until': '31-AUG-18', 'ac_operator': 'CX ', 'ac_owner': 'CX', 'ac_subtype': '7CF', 'ac_logical_no': 3, 'ac_state': 'R', 'dry_operating_wgt': 1, 'max_takeoff_wgt': 1, 'cargo_capacity': 0, 'fuel_capacity': 0, 'avg_fuel_consump': 0, 'ac_index': 190, 'crewsize_cockpit': 0, 'crewsize_cabin': 0, 'std_version': 'STN', 'ap_restriction': 'N', 'ac_owner_name': 'CX                            ', 'ac_subtype_name': '7CF                           ', 'ac_category': 'J', 'remark': '-                                                                               ', 'fuel_measure_unit': 'kg ', 'ac_callsign': None, 'radio': None, 'noise': None, 'phone': None, 'special_equipment': None, 'acars': 'S', 'alt_reg': None, 'record_id': 309080, 'last_update': '02-MAR-22', 'last_update_user_id': 'netline', 'std_version_alt_1': None, 'std_version_alt_2': None, 'std_version_alt_3': None, 'std_version_alt_4': None, 'ils_equipment': 'I', 'autoland': 'Y', 'homebase': None}, 'url': 'https://errors.pydantic.dev/2.12/v/missing'}\n",
      "      ... and 20 more errors\n",
      "\n",
      "======================================================================\n",
      "Performance Comparison: Single vs Batch Validation\n",
      "======================================================================\n",
      "\n",
      "Single validation (validate_with_contract) - generates model each time:\n",
      "  Time for 5 records: 0.139 seconds\n",
      "  Average per record: 27.75 ms\n",
      "\n",
      "Batch validation (validate_batch_with_contract) - generates model once:\n",
      "  Time for 5 records: 0.028 seconds\n",
      "  Average per record: 5.70 ms\n",
      "\n",
      "  Batch validation is 4.9x faster!\n",
      "  Recommendation: Use validate_batch_with_contract() for multiple records\n",
      "\n",
      "======================================================================\n",
      "Using Validated Data\n",
      "======================================================================\n",
      "\n",
      "✓ Created 0 valid Aircraft instances\n"
     ]
    }
   ],
   "source": [
    "# Step 6: Batch Validation Demonstration\n",
    "print(\"\\n\" + \"=\" * 70)\n",
    "print(\"Step 6: Batch Validation with Multiple Records\")\n",
    "print(\"=\" * 70)\n",
    "\n",
    "# Import validation functions\n",
    "from pycharter import validate_batch_with_contract, validate_with_contract\n",
    "\n",
    "# Prepare a batch of records from the CSV data\n",
    "if df is not None and len(df) > 0:\n",
    "    # Take a sample of records for demonstration (first 10 records)\n",
    "    sample_size = min(10, len(df))\n",
    "    print(f\"\\nPreparing {sample_size} records for batch validation...\")\n",
    "    \n",
    "    # Convert DataFrame rows to dictionaries\n",
    "    data_batch = []\n",
    "    for idx in range(sample_size):\n",
    "        row = df.iloc[idx].to_dict()\n",
    "        # Clean up the data - handle NaN values and convert datetime objects\n",
    "        cleaned_data = {}\n",
    "        for key, value in row.items():\n",
    "            # Convert column names to lowercase (matching schema property names)\n",
    "            field_name = key.lower() if isinstance(key, str) else key\n",
    "            \n",
    "            if pd.isna(value):\n",
    "                cleaned_data[field_name] = None\n",
    "            elif isinstance(value, pd.Timestamp):\n",
    "                cleaned_data[field_name] = value.isoformat()\n",
    "            elif isinstance(value, (int, float)) and pd.isna(value):\n",
    "                cleaned_data[field_name] = None\n",
    "            else:\n",
    "                cleaned_data[field_name] = value\n",
    "        \n",
    "        data_batch.append(cleaned_data)\n",
    "    \n",
    "    print(f\"✓ Prepared {len(data_batch)} records for validation\")\n",
    "    \n",
    "    # Perform batch validation\n",
    "    # This is efficient because the model is generated once and reused for all records\n",
    "    print(f\"\\nValidating batch of {len(data_batch)} records...\")\n",
    "    import time\n",
    "    start_time = time.time()\n",
    "    \n",
    "    validation_results = validate_batch_with_contract(\n",
    "        contract=reconstructed_contract,\n",
    "        data_list=data_batch,\n",
    "        model_name=\"Aircraft\"\n",
    "    )\n",
    "    \n",
    "    elapsed_time = time.time() - start_time\n",
    "    \n",
    "    # Analyze results\n",
    "    valid_count = sum(1 for r in validation_results if r.is_valid)\n",
    "    invalid_count = len(validation_results) - valid_count\n",
    "    \n",
    "    print(f\"✓ Batch validation completed in {elapsed_time:.3f} seconds\")\n",
    "    print(f\"\\nValidation Summary:\")\n",
    "    print(f\"  Total records: {len(validation_results)}\")\n",
    "    print(f\"  Valid records: {valid_count} ({valid_count/len(validation_results)*100:.1f}%)\")\n",
    "    print(f\"  Invalid records: {invalid_count} ({invalid_count/len(validation_results)*100:.1f}%)\")\n",
    "    print(f\"  Average time per record: {elapsed_time/len(validation_results)*1000:.2f} ms\")\n",
    "    \n",
    "    # Show details of invalid records\n",
    "    if invalid_count > 0:\n",
    "        print(f\"\\nInvalid Records Details:\")\n",
    "        for idx, result in enumerate(validation_results):\n",
    "            if not result.is_valid:\n",
    "                print(f\"\\n  Record {idx + 1}:\")\n",
    "                print(f\"    Errors: {len(result.errors)}\")\n",
    "                # Show first 3 errors (errors are strings, not dicts)\n",
    "                for error in result.errors[:3]:\n",
    "                    print(f\"      - {error}\")\n",
    "                if len(result.errors) > 3:\n",
    "                    print(f\"      ... and {len(result.errors) - 3} more errors\")\n",
    "    \n",
    "    # Show examples of valid records\n",
    "    if valid_count > 0:\n",
    "        print(f\"\\nValid Records Examples:\")\n",
    "        shown = 0\n",
    "        for idx, result in enumerate(validation_results):\n",
    "            if result.is_valid and shown < 3:\n",
    "                # result.data is the Pydantic model instance\n",
    "                if result.data:\n",
    "                    validated_data = result.data.model_dump()\n",
    "                    registration = validated_data.get('registration', 'N/A')\n",
    "                    ac_operator = validated_data.get('ac_operator', 'N/A')\n",
    "                    print(f\"  Record {idx + 1}: Registration={registration}, Operator={ac_operator}\")\n",
    "                    shown += 1\n",
    "    \n",
    "    # Demonstrate efficiency: Compare single vs batch validation\n",
    "    print(f\"\\n\" + \"=\" * 70)\n",
    "    print(\"Performance Comparison: Single vs Batch Validation\")\n",
    "    print(\"=\" * 70)\n",
    "    \n",
    "    # Single validation (inefficient - generates model each time)\n",
    "    print(f\"\\nSingle validation (validate_with_contract) - generates model each time:\")\n",
    "    single_start = time.time()\n",
    "    single_results = []\n",
    "    for data in data_batch[:5]:  # Test with first 5 records\n",
    "        result = validate_with_contract(contract=reconstructed_contract, data=data)\n",
    "        single_results.append(result)\n",
    "    single_elapsed = time.time() - single_start\n",
    "    print(f\"  Time for 5 records: {single_elapsed:.3f} seconds\")\n",
    "    print(f\"  Average per record: {single_elapsed/5*1000:.2f} ms\")\n",
    "    \n",
    "    # Batch validation (efficient - generates model once)\n",
    "    print(f\"\\nBatch validation (validate_batch_with_contract) - generates model once:\")\n",
    "    batch_start = time.time()\n",
    "    batch_results = validate_batch_with_contract(\n",
    "        contract=reconstructed_contract,\n",
    "        data_list=data_batch[:5]  # Same 5 records\n",
    "    )\n",
    "    batch_elapsed = time.time() - batch_start\n",
    "    print(f\"  Time for 5 records: {batch_elapsed:.3f} seconds\")\n",
    "    print(f\"  Average per record: {batch_elapsed/5*1000:.2f} ms\")\n",
    "    \n",
    "    if single_elapsed > 0:\n",
    "        speedup = single_elapsed / batch_elapsed\n",
    "        print(f\"\\n  Batch validation is {speedup:.1f}x faster!\")\n",
    "        print(f\"  Recommendation: Use validate_batch_with_contract() for multiple records\")\n",
    "    \n",
    "    # Show how to use the validated data\n",
    "    print(f\"\\n\" + \"=\" * 70)\n",
    "    print(\"Using Validated Data\")\n",
    "    print(\"=\" * 70)\n",
    "    \n",
    "    # Create Pydantic instances from validated data\n",
    "    # Note: result.data already contains the validated Pydantic instance\n",
    "    valid_instances = []\n",
    "    for idx, result in enumerate(validation_results):\n",
    "        if result.is_valid and result.data:\n",
    "            # result.data is already the validated Pydantic model instance\n",
    "            valid_instances.append(result.data)\n",
    "    \n",
    "    print(f\"\\n✓ Created {len(valid_instances)} valid Aircraft instances\")\n",
    "    if len(valid_instances) > 0:\n",
    "        print(f\"\\nExample instance:\")\n",
    "        example = valid_instances[0]\n",
    "        print(f\"  Registration: {example.registration}\")\n",
    "        print(f\"  AC Operator: {example.ac_operator}\")\n",
    "        print(f\"  AC Owner: {example.ac_owner}\")\n",
    "        print(f\"  AC State: {example.ac_state}\")\n",
    "        print(f\"  Valid Since: {example.valid_since}\")\n",
    "        print(f\"  Valid Until: {example.valid_until}\")\n",
    "    \n",
    "else:\n",
    "    print(\"\\n⚠ No CSV data available for batch validation\")\n",
    "    print(\"  Batch validation requires data from the CSV file\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4c022d6c-339e-432a-99b2-d82627057528",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "077073b5-ca14-44cd-977c-49b07242d9fc",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d7c4de73",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python (pycharter-dev)",
   "language": "python",
   "name": "pycharter-dev"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
