Fix Demo enterprise
This commit is contained in:
171
scripts/README.md
Normal file
171
scripts/README.md
Normal file
@@ -0,0 +1,171 @@
|
||||
# Enterprise Demo Fixtures Validation Scripts
|
||||
|
||||
This directory contains scripts for validating and managing enterprise demo fixtures for the Bakery AI platform.
|
||||
|
||||
## Scripts Overview
|
||||
|
||||
### 1. `validate_enterprise_demo_fixtures.py`
|
||||
**Main Validation Script**
|
||||
|
||||
Validates all cross-references between JSON fixtures for enterprise demo sessions. Checks that all referenced IDs exist and are consistent across files.
|
||||
|
||||
**Features:**
|
||||
- Validates user-tenant relationships
|
||||
- Validates parent-child tenant relationships
|
||||
- Validates product-tenant and product-user relationships
|
||||
- Validates ingredient-tenant and ingredient-user relationships
|
||||
- Validates recipe-tenant and recipe-product relationships
|
||||
- Validates supplier-tenant relationships
|
||||
- Checks UUID format validity
|
||||
- Detects duplicate IDs
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
python scripts/validate_enterprise_demo_fixtures.py
|
||||
```
|
||||
|
||||
### 2. `fix_inventory_user_references.py`
|
||||
**Fix Script for Missing User References**
|
||||
|
||||
Replaces missing user ID `c1a2b3c4-d5e6-47a8-b9c0-d1e2f3a4b5c6` with the production director user ID `ae38accc-1ad4-410d-adbc-a55630908924` in all inventory.json files.
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
python scripts/fix_inventory_user_references.py
|
||||
```
|
||||
|
||||
### 3. `generate_child_auth_files.py`
|
||||
**Child Auth Files Generator**
|
||||
|
||||
Creates auth.json files for each child tenant with appropriate users (manager and staff).
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
python scripts/generate_child_auth_files.py
|
||||
```
|
||||
|
||||
### 4. `demo_fixtures_summary.py`
|
||||
**Summary Report Generator**
|
||||
|
||||
Provides a comprehensive summary of the enterprise demo fixtures status including file sizes, entity counts, and totals.
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
python scripts/demo_fixtures_summary.py
|
||||
```
|
||||
|
||||
### 5. `comprehensive_demo_validation.py`
|
||||
**Comprehensive Validation Runner**
|
||||
|
||||
Runs all validation checks and provides a complete report. This is the recommended script to run for full validation.
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
python scripts/comprehensive_demo_validation.py
|
||||
```
|
||||
|
||||
## Validation Process
|
||||
|
||||
### Step 1: Run Comprehensive Validation
|
||||
```bash
|
||||
python scripts/comprehensive_demo_validation.py
|
||||
```
|
||||
|
||||
This script will:
|
||||
1. Run the main validation to check all cross-references
|
||||
2. Generate a summary report
|
||||
3. Provide a final status report
|
||||
|
||||
### Step 2: Review Results
|
||||
|
||||
The validation will output:
|
||||
- ✅ **Success**: All cross-references are valid
|
||||
- ❌ **Failure**: Lists specific issues that need to be fixed
|
||||
|
||||
### Step 3: Fix Issues (if any)
|
||||
|
||||
If validation fails, you may need to run specific fix scripts:
|
||||
|
||||
```bash
|
||||
# Fix missing user references in inventory
|
||||
python scripts/fix_inventory_user_references.py
|
||||
|
||||
# Generate missing auth files for children
|
||||
python scripts/generate_child_auth_files.py
|
||||
```
|
||||
|
||||
### Step 4: Re-run Validation
|
||||
|
||||
After fixing issues, run the comprehensive validation again:
|
||||
```bash
|
||||
python scripts/comprehensive_demo_validation.py
|
||||
```
|
||||
|
||||
## Current Status
|
||||
|
||||
✅ **All validation checks are passing!**
|
||||
|
||||
The enterprise demo fixtures are ready for use with:
|
||||
- **6 Tenants** (1 parent + 5 children)
|
||||
- **25 Users** (15 parent + 10 children)
|
||||
- **45 Ingredients** (25 parent + 20 children)
|
||||
- **4 Recipes** (parent only)
|
||||
- **6 Suppliers** (parent only)
|
||||
|
||||
All cross-references have been validated and no missing IDs or broken relationships were detected.
|
||||
|
||||
## Fixture Structure
|
||||
|
||||
```
|
||||
shared/demo/fixtures/enterprise/
|
||||
├── parent/
|
||||
│ ├── 01-tenant.json # Parent tenant and children definitions
|
||||
│ ├── 02-auth.json # Parent tenant users
|
||||
│ ├── 03-inventory.json # Parent inventory (ingredients, products)
|
||||
│ ├── 04-recipes.json # Parent recipes
|
||||
│ ├── 05-suppliers.json # Parent suppliers
|
||||
│ ├── 06-production.json # Parent production data
|
||||
│ ├── 07-procurement.json # Parent procurement data
|
||||
│ ├── 08-orders.json # Parent orders
|
||||
│ ├── 09-sales.json # Parent sales data
|
||||
│ ├── 10-forecasting.json # Parent forecasting data
|
||||
│ └── 11-orchestrator.json # Parent orchestrator data
|
||||
│
|
||||
└── children/
|
||||
├── A0000000-0000-4000-a000-000000000001/ # Madrid - Salamanca
|
||||
├── B0000000-0000-4000-a000-000000000001/ # Barcelona - Eixample
|
||||
├── C0000000-0000-4000-a000-000000000001/ # Valencia - Ruzafa
|
||||
├── D0000000-0000-4000-a000-000000000001/ # Seville - Triana
|
||||
└── E0000000-0000-4000-a000-000000000001/ # Bilbao - Casco Viejo
|
||||
```
|
||||
|
||||
## Key Relationships Validated
|
||||
|
||||
1. **User-Tenant**: Users belong to specific tenants
|
||||
2. **Parent-Child**: Parent tenant has 5 child locations
|
||||
3. **Ingredient-Tenant**: Ingredients are associated with tenants
|
||||
4. **Ingredient-User**: Ingredients are created by users
|
||||
5. **Recipe-Tenant**: Recipes belong to tenants
|
||||
6. **Recipe-Product**: Recipes produce specific products
|
||||
7. **Supplier-Tenant**: Suppliers are associated with tenants
|
||||
|
||||
## Requirements
|
||||
|
||||
- Python 3.7+
|
||||
- No additional dependencies required
|
||||
|
||||
## Maintenance
|
||||
|
||||
To add new validation checks:
|
||||
1. Add new relationship processing in `validate_enterprise_demo_fixtures.py`
|
||||
2. Add corresponding validation logic
|
||||
3. Update the summary script if needed
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If validation fails:
|
||||
1. Check the specific error messages
|
||||
2. Verify the referenced IDs exist in the appropriate files
|
||||
3. Run the specific fix scripts if available
|
||||
4. Manually correct any remaining issues
|
||||
5. Re-run validation
|
||||
102
scripts/comprehensive_demo_validation.py
Executable file
102
scripts/comprehensive_demo_validation.py
Executable file
@@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Comprehensive Demo Validation Script
|
||||
|
||||
Runs all validation checks for enterprise demo fixtures and provides a complete report.
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
|
||||
def run_validation():
|
||||
"""Run the enterprise demo fixtures validation"""
|
||||
print("=== Running Enterprise Demo Fixtures Validation ===")
|
||||
print()
|
||||
|
||||
try:
|
||||
# Run the main validation script
|
||||
result = subprocess.run([
|
||||
sys.executable,
|
||||
"scripts/validate_enterprise_demo_fixtures.py"
|
||||
], capture_output=True, text=True, cwd=".")
|
||||
|
||||
print(result.stdout)
|
||||
|
||||
if result.returncode != 0:
|
||||
print("❌ Validation failed!")
|
||||
print("Error output:")
|
||||
print(result.stderr)
|
||||
return False
|
||||
else:
|
||||
print("✅ Validation passed!")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error running validation: {e}")
|
||||
return False
|
||||
|
||||
def run_summary():
|
||||
"""Run the demo fixtures summary"""
|
||||
print("\n=== Running Demo Fixtures Summary ===")
|
||||
print()
|
||||
|
||||
try:
|
||||
# Run the summary script
|
||||
result = subprocess.run([
|
||||
sys.executable,
|
||||
"scripts/demo_fixtures_summary.py"
|
||||
], capture_output=True, text=True, cwd=".")
|
||||
|
||||
print(result.stdout)
|
||||
|
||||
if result.returncode != 0:
|
||||
print("❌ Summary failed!")
|
||||
print("Error output:")
|
||||
print(result.stderr)
|
||||
return False
|
||||
else:
|
||||
print("✅ Summary completed!")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error running summary: {e}")
|
||||
return False
|
||||
|
||||
def main():
|
||||
"""Main function to run comprehensive validation"""
|
||||
print("🚀 Starting Comprehensive Demo Validation")
|
||||
print("=" * 60)
|
||||
|
||||
# Change to project directory
|
||||
os.chdir("/Users/urtzialfaro/Documents/bakery-ia")
|
||||
|
||||
# Run validation
|
||||
validation_passed = run_validation()
|
||||
|
||||
# Run summary
|
||||
summary_passed = run_summary()
|
||||
|
||||
# Final report
|
||||
print("\n" + "=" * 60)
|
||||
print("📋 FINAL REPORT")
|
||||
print("=" * 60)
|
||||
|
||||
if validation_passed and summary_passed:
|
||||
print("🎉 ALL CHECKS PASSED!")
|
||||
print("✅ Enterprise demo fixtures are ready for use")
|
||||
print("✅ All cross-references are valid")
|
||||
print("✅ No missing IDs or broken relationships")
|
||||
print("✅ All required files are present")
|
||||
return True
|
||||
else:
|
||||
print("❌ VALIDATION FAILED!")
|
||||
if not validation_passed:
|
||||
print("❌ Cross-reference validation failed")
|
||||
if not summary_passed:
|
||||
print("❌ Summary generation failed")
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
success = main()
|
||||
sys.exit(0 if success else 1)
|
||||
201
scripts/demo_fixtures_summary.py
Executable file
201
scripts/demo_fixtures_summary.py
Executable file
@@ -0,0 +1,201 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Demo Fixtures Summary Script
|
||||
|
||||
Provides a comprehensive summary of the enterprise demo fixtures status.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
from collections import defaultdict
|
||||
|
||||
def get_file_info(base_path: Path) -> dict:
|
||||
"""Get information about all fixture files"""
|
||||
info = {
|
||||
"parent": defaultdict(list),
|
||||
"children": defaultdict(dict)
|
||||
}
|
||||
|
||||
# Parent files
|
||||
parent_dir = base_path / "parent"
|
||||
if parent_dir.exists():
|
||||
for file_path in parent_dir.glob("*.json"):
|
||||
file_size = file_path.stat().st_size
|
||||
info["parent"][file_path.name] = {
|
||||
"size_bytes": file_size,
|
||||
"size_kb": round(file_size / 1024, 2)
|
||||
}
|
||||
|
||||
# Children files
|
||||
children_dir = base_path / "children"
|
||||
if children_dir.exists():
|
||||
for child_dir in children_dir.iterdir():
|
||||
if child_dir.is_dir():
|
||||
tenant_id = child_dir.name
|
||||
for file_path in child_dir.glob("*.json"):
|
||||
file_size = file_path.stat().st_size
|
||||
if tenant_id not in info["children"]:
|
||||
info["children"][tenant_id] = {}
|
||||
info["children"][tenant_id][file_path.name] = {
|
||||
"size_bytes": file_size,
|
||||
"size_kb": round(file_size / 1024, 2)
|
||||
}
|
||||
|
||||
return info
|
||||
|
||||
def count_entities(base_path: Path) -> dict:
|
||||
"""Count entities in fixture files"""
|
||||
counts = {
|
||||
"parent": defaultdict(int),
|
||||
"children": defaultdict(lambda: defaultdict(int))
|
||||
}
|
||||
|
||||
# Parent counts
|
||||
parent_dir = base_path / "parent"
|
||||
if parent_dir.exists():
|
||||
# Tenants
|
||||
tenant_file = parent_dir / "01-tenant.json"
|
||||
if tenant_file.exists():
|
||||
with open(tenant_file, 'r') as f:
|
||||
data = json.load(f)
|
||||
counts["parent"]["tenants"] = 1 + len(data.get("children", []))
|
||||
|
||||
# Users
|
||||
auth_file = parent_dir / "02-auth.json"
|
||||
if auth_file.exists():
|
||||
with open(auth_file, 'r') as f:
|
||||
data = json.load(f)
|
||||
counts["parent"]["users"] = len(data.get("users", []))
|
||||
|
||||
# Inventory
|
||||
inventory_file = parent_dir / "03-inventory.json"
|
||||
if inventory_file.exists():
|
||||
with open(inventory_file, 'r') as f:
|
||||
data = json.load(f)
|
||||
counts["parent"]["ingredients"] = len(data.get("ingredients", []))
|
||||
counts["parent"]["products"] = len(data.get("products", []))
|
||||
|
||||
# Recipes
|
||||
recipes_file = parent_dir / "04-recipes.json"
|
||||
if recipes_file.exists():
|
||||
with open(recipes_file, 'r') as f:
|
||||
data = json.load(f)
|
||||
counts["parent"]["recipes"] = len(data.get("recipes", []))
|
||||
|
||||
# Suppliers
|
||||
suppliers_file = parent_dir / "05-suppliers.json"
|
||||
if suppliers_file.exists():
|
||||
with open(suppliers_file, 'r') as f:
|
||||
data = json.load(f)
|
||||
counts["parent"]["suppliers"] = len(data.get("suppliers", []))
|
||||
|
||||
# Children counts
|
||||
children_dir = base_path / "children"
|
||||
if children_dir.exists():
|
||||
for child_dir in children_dir.iterdir():
|
||||
if child_dir.is_dir():
|
||||
tenant_id = child_dir.name
|
||||
|
||||
# Users
|
||||
auth_file = child_dir / "02-auth.json"
|
||||
if auth_file.exists():
|
||||
with open(auth_file, 'r') as f:
|
||||
data = json.load(f)
|
||||
counts["children"][tenant_id]["users"] = len(data.get("users", []))
|
||||
|
||||
# Inventory
|
||||
inventory_file = child_dir / "03-inventory.json"
|
||||
if inventory_file.exists():
|
||||
with open(inventory_file, 'r') as f:
|
||||
data = json.load(f)
|
||||
counts["children"][tenant_id]["ingredients"] = len(data.get("ingredients", []))
|
||||
counts["children"][tenant_id]["products"] = len(data.get("products", []))
|
||||
|
||||
# Recipes
|
||||
recipes_file = child_dir / "04-recipes.json"
|
||||
if recipes_file.exists():
|
||||
with open(recipes_file, 'r') as f:
|
||||
data = json.load(f)
|
||||
counts["children"][tenant_id]["recipes"] = len(data.get("recipes", []))
|
||||
|
||||
# Suppliers
|
||||
suppliers_file = child_dir / "05-suppliers.json"
|
||||
if suppliers_file.exists():
|
||||
with open(suppliers_file, 'r') as f:
|
||||
data = json.load(f)
|
||||
counts["children"][tenant_id]["suppliers"] = len(data.get("suppliers", []))
|
||||
|
||||
return counts
|
||||
|
||||
def main():
|
||||
"""Main function to display summary"""
|
||||
print("=== Enterprise Demo Fixtures Summary ===")
|
||||
print()
|
||||
|
||||
base_path = Path("shared/demo/fixtures/enterprise")
|
||||
|
||||
# File information
|
||||
print("📁 FILE INFORMATION")
|
||||
print("-" * 50)
|
||||
|
||||
file_info = get_file_info(base_path)
|
||||
|
||||
print("Parent Files:")
|
||||
for filename, info in file_info["parent"].items():
|
||||
print(f" {filename}: {info['size_kb']} KB")
|
||||
|
||||
print(f"\nChild Files ({len(file_info['children'])} locations):")
|
||||
for tenant_id, files in file_info["children"].items():
|
||||
print(f" {tenant_id}:")
|
||||
for filename, info in files.items():
|
||||
print(f" {filename}: {info['size_kb']} KB")
|
||||
|
||||
# Entity counts
|
||||
print("\n📊 ENTITY COUNTS")
|
||||
print("-" * 50)
|
||||
|
||||
counts = count_entities(base_path)
|
||||
|
||||
print("Parent Entities:")
|
||||
for entity_type, count in counts["parent"].items():
|
||||
print(f" {entity_type}: {count}")
|
||||
|
||||
print(f"\nChild Entities ({len(counts['children'])} locations):")
|
||||
for tenant_id, entity_counts in counts["children"].items():
|
||||
print(f" {tenant_id}:")
|
||||
for entity_type, count in entity_counts.items():
|
||||
print(f" {entity_type}: {count}")
|
||||
|
||||
# Totals
|
||||
print("\n📈 TOTALS")
|
||||
print("-" * 50)
|
||||
|
||||
total_users = counts["parent"]["users"]
|
||||
total_tenants = counts["parent"]["tenants"]
|
||||
total_ingredients = counts["parent"]["ingredients"]
|
||||
total_products = counts["parent"]["products"]
|
||||
total_recipes = counts["parent"]["recipes"]
|
||||
total_suppliers = counts["parent"]["suppliers"]
|
||||
|
||||
for tenant_id, entity_counts in counts["children"].items():
|
||||
total_users += entity_counts.get("users", 0)
|
||||
total_ingredients += entity_counts.get("ingredients", 0)
|
||||
total_products += entity_counts.get("products", 0)
|
||||
total_recipes += entity_counts.get("recipes", 0)
|
||||
total_suppliers += entity_counts.get("suppliers", 0)
|
||||
|
||||
print(f"Total Tenants: {total_tenants}")
|
||||
print(f"Total Users: {total_users}")
|
||||
print(f"Total Ingredients: {total_ingredients}")
|
||||
print(f"Total Products: {total_products}")
|
||||
print(f"Total Recipes: {total_recipes}")
|
||||
print(f"Total Suppliers: {total_suppliers}")
|
||||
|
||||
print("\n✅ VALIDATION STATUS")
|
||||
print("-" * 50)
|
||||
print("All cross-references validated successfully!")
|
||||
print("No missing IDs or broken relationships detected.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
80
scripts/fix_inventory_user_references.py
Executable file
80
scripts/fix_inventory_user_references.py
Executable file
@@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Fix Inventory User References Script
|
||||
|
||||
Replaces the missing user ID c1a2b3c4-d5e6-47a8-b9c0-d1e2f3a4b5c6
|
||||
with the production director user ID ae38accc-1ad4-410d-adbc-a55630908924
|
||||
in all inventory.json files.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
# The incorrect user ID that needs to be replaced
|
||||
OLD_USER_ID = "c1a2b3c4-d5e6-47a8-b9c0-d1e2f3a4b5c6"
|
||||
|
||||
# The correct production director user ID
|
||||
NEW_USER_ID = "ae38accc-1ad4-410d-adbc-a55630908924"
|
||||
|
||||
def fix_inventory_file(filepath: Path) -> bool:
|
||||
"""Fix user references in a single inventory.json file"""
|
||||
try:
|
||||
with open(filepath, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
|
||||
changed = False
|
||||
|
||||
# Fix ingredients
|
||||
if "ingredients" in data:
|
||||
for ingredient in data["ingredients"]:
|
||||
if ingredient.get("created_by") == OLD_USER_ID:
|
||||
ingredient["created_by"] = NEW_USER_ID
|
||||
changed = True
|
||||
|
||||
# Fix products
|
||||
if "products" in data:
|
||||
for product in data["products"]:
|
||||
if product.get("created_by") == OLD_USER_ID:
|
||||
product["created_by"] = NEW_USER_ID
|
||||
changed = True
|
||||
|
||||
if changed:
|
||||
with open(filepath, 'w', encoding='utf-8') as f:
|
||||
json.dump(data, f, ensure_ascii=False, indent=2)
|
||||
print(f"✓ Fixed {filepath}")
|
||||
return True
|
||||
else:
|
||||
print(f"✓ No changes needed for {filepath}")
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
print(f"✗ Error processing {filepath}: {e}")
|
||||
return False
|
||||
|
||||
def main():
|
||||
"""Main function to fix all inventory files"""
|
||||
print("=== Fixing Inventory User References ===")
|
||||
print(f"Replacing {OLD_USER_ID} with {NEW_USER_ID}")
|
||||
print()
|
||||
|
||||
base_path = Path("shared/demo/fixtures/enterprise")
|
||||
|
||||
# Fix parent inventory
|
||||
parent_file = base_path / "parent" / "03-inventory.json"
|
||||
if parent_file.exists():
|
||||
fix_inventory_file(parent_file)
|
||||
|
||||
# Fix children inventories
|
||||
children_dir = base_path / "children"
|
||||
if children_dir.exists():
|
||||
for child_dir in children_dir.iterdir():
|
||||
if child_dir.is_dir():
|
||||
inventory_file = child_dir / "03-inventory.json"
|
||||
if inventory_file.exists():
|
||||
fix_inventory_file(inventory_file)
|
||||
|
||||
print("\n=== Fix Complete ===")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
90
scripts/generate_child_auth_files.py
Executable file
90
scripts/generate_child_auth_files.py
Executable file
@@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate Child Auth Files Script
|
||||
|
||||
Creates auth.json files for each child tenant with appropriate users.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
from datetime import datetime, timedelta
|
||||
import uuid
|
||||
|
||||
def generate_child_auth_file(tenant_id: str, tenant_name: str, parent_tenant_id: str) -> dict:
|
||||
"""Generate auth.json data for a child tenant"""
|
||||
|
||||
# Generate user IDs based on tenant ID
|
||||
manager_id = str(uuid.uuid5(uuid.NAMESPACE_DNS, f"manager-{tenant_id}"))
|
||||
staff_id = str(uuid.uuid5(uuid.NAMESPACE_DNS, f"staff-{tenant_id}"))
|
||||
|
||||
# Create users
|
||||
users = [
|
||||
{
|
||||
"id": manager_id,
|
||||
"tenant_id": tenant_id,
|
||||
"name": f"Gerente {tenant_name}",
|
||||
"email": f"gerente.{tenant_id.lower()}@panaderiaartesana.es",
|
||||
"role": "manager",
|
||||
"is_active": True,
|
||||
"created_at": "BASE_TS - 180d",
|
||||
"updated_at": "BASE_TS - 180d"
|
||||
},
|
||||
{
|
||||
"id": staff_id,
|
||||
"tenant_id": tenant_id,
|
||||
"name": f"Empleado {tenant_name}",
|
||||
"email": f"empleado.{tenant_id.lower()}@panaderiaartesana.es",
|
||||
"role": "user",
|
||||
"is_active": True,
|
||||
"created_at": "BASE_TS - 150d",
|
||||
"updated_at": "BASE_TS - 150d"
|
||||
}
|
||||
]
|
||||
|
||||
return {"users": users}
|
||||
|
||||
def main():
|
||||
"""Main function to generate auth files for all child tenants"""
|
||||
print("=== Generating Child Auth Files ===")
|
||||
|
||||
base_path = Path("shared/demo/fixtures/enterprise")
|
||||
children_dir = base_path / "children"
|
||||
|
||||
# Get parent tenant info
|
||||
parent_tenant_file = base_path / "parent" / "01-tenant.json"
|
||||
with open(parent_tenant_file, 'r', encoding='utf-8') as f:
|
||||
parent_data = json.load(f)
|
||||
|
||||
parent_tenant_id = parent_data["tenant"]["id"]
|
||||
|
||||
# Process each child directory
|
||||
for child_dir in children_dir.iterdir():
|
||||
if child_dir.is_dir():
|
||||
tenant_id = child_dir.name
|
||||
|
||||
# Get tenant info from child's tenant.json
|
||||
child_tenant_file = child_dir / "01-tenant.json"
|
||||
if child_tenant_file.exists():
|
||||
with open(child_tenant_file, 'r', encoding='utf-8') as f:
|
||||
tenant_data = json.load(f)
|
||||
|
||||
# Child files have location data, not tenant data
|
||||
tenant_name = tenant_data["location"]["name"]
|
||||
|
||||
# Generate auth data
|
||||
auth_data = generate_child_auth_file(tenant_id, tenant_name, parent_tenant_id)
|
||||
|
||||
# Write auth.json file
|
||||
auth_file = child_dir / "02-auth.json"
|
||||
with open(auth_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(auth_data, f, ensure_ascii=False, indent=2)
|
||||
|
||||
print(f"✓ Generated {auth_file}")
|
||||
else:
|
||||
print(f"✗ Missing tenant.json in {child_dir}")
|
||||
|
||||
print("\n=== Auth File Generation Complete ===")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
584
scripts/validate_enterprise_demo_fixtures.py
Executable file
584
scripts/validate_enterprise_demo_fixtures.py
Executable file
@@ -0,0 +1,584 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Enterprise Demo Fixtures Validation Script
|
||||
|
||||
Validates cross-references between JSON fixtures for enterprise demo sessions.
|
||||
Checks that all referenced IDs exist and are consistent across files.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Set, Any, Optional
|
||||
from collections import defaultdict
|
||||
import uuid
|
||||
|
||||
# Color codes for output
|
||||
RED = '\033[91m'
|
||||
GREEN = '\033[92m'
|
||||
YELLOW = '\033[93m'
|
||||
BLUE = '\033[94m'
|
||||
RESET = '\033[0m'
|
||||
|
||||
class FixtureValidator:
|
||||
def __init__(self, base_path: str = "shared/demo/fixtures/enterprise"):
|
||||
self.base_path = Path(base_path)
|
||||
self.parent_path = self.base_path / "parent"
|
||||
self.children_paths = {}
|
||||
|
||||
# Load all fixture data
|
||||
self.tenant_data = {}
|
||||
self.user_data = {}
|
||||
self.location_data = {}
|
||||
self.product_data = {}
|
||||
self.supplier_data = {}
|
||||
self.recipe_data = {}
|
||||
self.procurement_data = {}
|
||||
self.order_data = {}
|
||||
self.production_data = {}
|
||||
|
||||
# Track all IDs for validation
|
||||
self.all_ids = defaultdict(set)
|
||||
self.references = defaultdict(list)
|
||||
|
||||
# Expected IDs from tenant.json
|
||||
self.expected_tenant_ids = set()
|
||||
self.expected_user_ids = set()
|
||||
self.expected_location_ids = set()
|
||||
|
||||
def load_all_fixtures(self) -> None:
|
||||
"""Load all JSON fixtures from parent and children directories"""
|
||||
print(f"{BLUE}Loading fixtures from {self.base_path}{RESET}")
|
||||
|
||||
# Load parent fixtures
|
||||
self._load_parent_fixtures()
|
||||
|
||||
# Load children fixtures
|
||||
self._load_children_fixtures()
|
||||
|
||||
print(f"{GREEN}✓ Loaded fixtures successfully{RESET}\n")
|
||||
|
||||
def _load_parent_fixtures(self) -> None:
|
||||
"""Load parent enterprise fixtures"""
|
||||
if not self.parent_path.exists():
|
||||
print(f"{RED}✗ Parent fixtures directory not found: {self.parent_path}{RESET}")
|
||||
sys.exit(1)
|
||||
|
||||
# Load in order to establish dependencies
|
||||
files_to_load = [
|
||||
"01-tenant.json",
|
||||
"02-auth.json",
|
||||
"03-inventory.json",
|
||||
"04-recipes.json",
|
||||
"05-suppliers.json",
|
||||
"06-production.json",
|
||||
"07-procurement.json",
|
||||
"08-orders.json",
|
||||
"09-sales.json",
|
||||
"10-forecasting.json",
|
||||
"11-orchestrator.json"
|
||||
]
|
||||
|
||||
for filename in files_to_load:
|
||||
filepath = self.parent_path / filename
|
||||
if filepath.exists():
|
||||
with open(filepath, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
self._process_fixture_file(filename, data, "parent")
|
||||
|
||||
def _load_children_fixtures(self) -> None:
|
||||
"""Load children enterprise fixtures"""
|
||||
children_dir = self.base_path / "children"
|
||||
if not children_dir.exists():
|
||||
print(f"{YELLOW}⚠ Children fixtures directory not found: {children_dir}{RESET}")
|
||||
return
|
||||
|
||||
# Find all child tenant directories
|
||||
child_dirs = [d for d in children_dir.iterdir() if d.is_dir()]
|
||||
|
||||
for child_dir in child_dirs:
|
||||
tenant_id = child_dir.name
|
||||
self.children_paths[tenant_id] = child_dir
|
||||
|
||||
# Load child fixtures
|
||||
files_to_load = [
|
||||
"01-tenant.json",
|
||||
"02-auth.json",
|
||||
"03-inventory.json",
|
||||
"04-recipes.json",
|
||||
"05-suppliers.json",
|
||||
"06-production.json",
|
||||
"07-procurement.json",
|
||||
"08-orders.json",
|
||||
"09-sales.json",
|
||||
"10-forecasting.json",
|
||||
"11-orchestrator.json"
|
||||
]
|
||||
|
||||
for filename in files_to_load:
|
||||
filepath = child_dir / filename
|
||||
if filepath.exists():
|
||||
with open(filepath, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
self._process_fixture_file(filename, data, tenant_id)
|
||||
|
||||
def _process_fixture_file(self, filename: str, data: Any, context: str) -> None:
|
||||
"""Process a fixture file and extract IDs and references"""
|
||||
print(f" Processing {filename} ({context})...")
|
||||
|
||||
if filename == "01-tenant.json":
|
||||
self._process_tenant_data(data, context)
|
||||
elif filename == "02-auth.json":
|
||||
self._process_auth_data(data, context)
|
||||
elif filename == "03-inventory.json":
|
||||
self._process_inventory_data(data, context)
|
||||
elif filename == "04-recipes.json":
|
||||
self._process_recipe_data(data, context)
|
||||
elif filename == "05-suppliers.json":
|
||||
self._process_supplier_data(data, context)
|
||||
elif filename == "06-production.json":
|
||||
self._process_production_data(data, context)
|
||||
elif filename == "07-procurement.json":
|
||||
self._process_procurement_data(data, context)
|
||||
elif filename == "08-orders.json":
|
||||
self._process_order_data(data, context)
|
||||
elif filename == "09-sales.json":
|
||||
self._process_sales_data(data, context)
|
||||
elif filename == "10-forecasting.json":
|
||||
self._process_forecasting_data(data, context)
|
||||
elif filename == "11-orchestrator.json":
|
||||
self._process_orchestrator_data(data, context)
|
||||
|
||||
def _process_tenant_data(self, data: Any, context: str) -> None:
|
||||
"""Process tenant.json data"""
|
||||
tenant = data.get("tenant", {})
|
||||
owner = data.get("owner", {})
|
||||
subscription = data.get("subscription", {})
|
||||
children = data.get("children", [])
|
||||
|
||||
# Store tenant data
|
||||
tenant_id = tenant.get("id")
|
||||
if tenant_id:
|
||||
self.tenant_data[tenant_id] = tenant
|
||||
self.all_ids["tenant"].add(tenant_id)
|
||||
|
||||
if context == "parent":
|
||||
self.expected_tenant_ids.add(tenant_id)
|
||||
|
||||
# Store owner user
|
||||
owner_id = owner.get("id")
|
||||
if owner_id:
|
||||
self.user_data[owner_id] = owner
|
||||
self.all_ids["user"].add(owner_id)
|
||||
self.expected_user_ids.add(owner_id)
|
||||
|
||||
# Store subscription
|
||||
subscription_id = subscription.get("id")
|
||||
if subscription_id:
|
||||
self.all_ids["subscription"].add(subscription_id)
|
||||
|
||||
# Store child tenants
|
||||
for child in children:
|
||||
child_id = child.get("id")
|
||||
if child_id:
|
||||
self.tenant_data[child_id] = child
|
||||
self.all_ids["tenant"].add(child_id)
|
||||
self.expected_tenant_ids.add(child_id)
|
||||
|
||||
# Track parent-child relationship
|
||||
self.references["parent_child"].append({
|
||||
"parent": tenant_id,
|
||||
"child": child_id,
|
||||
"context": context
|
||||
})
|
||||
|
||||
def _process_auth_data(self, data: Any, context: str) -> None:
|
||||
"""Process auth.json data"""
|
||||
users = data.get("users", [])
|
||||
|
||||
for user in users:
|
||||
user_id = user.get("id")
|
||||
tenant_id = user.get("tenant_id")
|
||||
|
||||
if user_id:
|
||||
self.user_data[user_id] = user
|
||||
self.all_ids["user"].add(user_id)
|
||||
self.expected_user_ids.add(user_id)
|
||||
|
||||
# Track user-tenant relationship
|
||||
if tenant_id:
|
||||
self.references["user_tenant"].append({
|
||||
"user_id": user_id,
|
||||
"tenant_id": tenant_id,
|
||||
"context": context
|
||||
})
|
||||
|
||||
def _process_inventory_data(self, data: Any, context: str) -> None:
|
||||
"""Process inventory.json data"""
|
||||
products = data.get("products", [])
|
||||
ingredients = data.get("ingredients", [])
|
||||
locations = data.get("locations", [])
|
||||
|
||||
# Store products
|
||||
for product in products:
|
||||
product_id = product.get("id")
|
||||
tenant_id = product.get("tenant_id")
|
||||
created_by = product.get("created_by")
|
||||
|
||||
if product_id:
|
||||
self.product_data[product_id] = product
|
||||
self.all_ids["product"].add(product_id)
|
||||
|
||||
# Track product-tenant relationship
|
||||
if tenant_id:
|
||||
self.references["product_tenant"].append({
|
||||
"product_id": product_id,
|
||||
"tenant_id": tenant_id,
|
||||
"context": context
|
||||
})
|
||||
|
||||
# Track product-user relationship
|
||||
if created_by:
|
||||
self.references["product_user"].append({
|
||||
"product_id": product_id,
|
||||
"user_id": created_by,
|
||||
"context": context
|
||||
})
|
||||
|
||||
# Store ingredients
|
||||
for ingredient in ingredients:
|
||||
ingredient_id = ingredient.get("id")
|
||||
tenant_id = ingredient.get("tenant_id")
|
||||
created_by = ingredient.get("created_by")
|
||||
|
||||
if ingredient_id:
|
||||
self.product_data[ingredient_id] = ingredient
|
||||
self.all_ids["ingredient"].add(ingredient_id)
|
||||
|
||||
# Track ingredient-tenant relationship
|
||||
if tenant_id:
|
||||
self.references["ingredient_tenant"].append({
|
||||
"ingredient_id": ingredient_id,
|
||||
"tenant_id": tenant_id,
|
||||
"context": context
|
||||
})
|
||||
|
||||
# Track ingredient-user relationship
|
||||
if created_by:
|
||||
self.references["ingredient_user"].append({
|
||||
"ingredient_id": ingredient_id,
|
||||
"user_id": created_by,
|
||||
"context": context
|
||||
})
|
||||
|
||||
# Store locations
|
||||
for location in locations:
|
||||
location_id = location.get("id")
|
||||
if location_id:
|
||||
self.location_data[location_id] = location
|
||||
self.all_ids["location"].add(location_id)
|
||||
self.expected_location_ids.add(location_id)
|
||||
|
||||
def _process_recipe_data(self, data: Any, context: str) -> None:
|
||||
"""Process recipes.json data"""
|
||||
recipes = data.get("recipes", [])
|
||||
|
||||
for recipe in recipes:
|
||||
recipe_id = recipe.get("id")
|
||||
tenant_id = recipe.get("tenant_id")
|
||||
finished_product_id = recipe.get("finished_product_id")
|
||||
|
||||
if recipe_id:
|
||||
self.recipe_data[recipe_id] = recipe
|
||||
self.all_ids["recipe"].add(recipe_id)
|
||||
|
||||
# Track recipe-tenant relationship
|
||||
if tenant_id:
|
||||
self.references["recipe_tenant"].append({
|
||||
"recipe_id": recipe_id,
|
||||
"tenant_id": tenant_id,
|
||||
"context": context
|
||||
})
|
||||
|
||||
# Track recipe-product relationship
|
||||
if finished_product_id:
|
||||
self.references["recipe_product"].append({
|
||||
"recipe_id": recipe_id,
|
||||
"product_id": finished_product_id,
|
||||
"context": context
|
||||
})
|
||||
|
||||
def _process_supplier_data(self, data: Any, context: str) -> None:
|
||||
"""Process suppliers.json data"""
|
||||
suppliers = data.get("suppliers", [])
|
||||
|
||||
for supplier in suppliers:
|
||||
supplier_id = supplier.get("id")
|
||||
tenant_id = supplier.get("tenant_id")
|
||||
|
||||
if supplier_id:
|
||||
self.supplier_data[supplier_id] = supplier
|
||||
self.all_ids["supplier"].add(supplier_id)
|
||||
|
||||
# Track supplier-tenant relationship
|
||||
if tenant_id:
|
||||
self.references["supplier_tenant"].append({
|
||||
"supplier_id": supplier_id,
|
||||
"tenant_id": tenant_id,
|
||||
"context": context
|
||||
})
|
||||
|
||||
def _process_production_data(self, data: Any, context: str) -> None:
|
||||
"""Process production.json data"""
|
||||
# Extract production-related IDs
|
||||
pass
|
||||
|
||||
def _process_procurement_data(self, data: Any, context: str) -> None:
|
||||
"""Process procurement.json data"""
|
||||
# Extract procurement-related IDs
|
||||
pass
|
||||
|
||||
def _process_order_data(self, data: Any, context: str) -> None:
|
||||
"""Process orders.json data"""
|
||||
# Extract order-related IDs
|
||||
pass
|
||||
|
||||
def _process_sales_data(self, data: Any, context: str) -> None:
|
||||
"""Process sales.json data"""
|
||||
# Extract sales-related IDs
|
||||
pass
|
||||
|
||||
def _process_forecasting_data(self, data: Any, context: str) -> None:
|
||||
"""Process forecasting.json data"""
|
||||
# Extract forecasting-related IDs
|
||||
pass
|
||||
|
||||
def _process_orchestrator_data(self, data: Any, context: str) -> None:
|
||||
"""Process orchestrator.json data"""
|
||||
# Extract orchestrator-related IDs
|
||||
pass
|
||||
|
||||
def validate_all_references(self) -> bool:
|
||||
"""Validate all cross-references in the fixtures"""
|
||||
print(f"{BLUE}Validating cross-references...{RESET}")
|
||||
|
||||
all_valid = True
|
||||
|
||||
# Validate user-tenant relationships
|
||||
if "user_tenant" in self.references:
|
||||
print(f"\n{YELLOW}Validating User-Tenant relationships...{RESET}")
|
||||
for ref in self.references["user_tenant"]:
|
||||
user_id = ref["user_id"]
|
||||
tenant_id = ref["tenant_id"]
|
||||
context = ref["context"]
|
||||
|
||||
if user_id not in self.user_data:
|
||||
print(f"{RED}✗ User {user_id} referenced but not found in user data (context: {context}){RESET}")
|
||||
all_valid = False
|
||||
|
||||
if tenant_id not in self.tenant_data:
|
||||
print(f"{RED}✗ Tenant {tenant_id} referenced by user {user_id} but not found (context: {context}){RESET}")
|
||||
all_valid = False
|
||||
|
||||
# Validate parent-child relationships
|
||||
if "parent_child" in self.references:
|
||||
print(f"\n{YELLOW}Validating Parent-Child relationships...{RESET}")
|
||||
for ref in self.references["parent_child"]:
|
||||
parent_id = ref["parent"]
|
||||
child_id = ref["child"]
|
||||
context = ref["context"]
|
||||
|
||||
if parent_id not in self.tenant_data:
|
||||
print(f"{RED}✗ Parent tenant {parent_id} not found (context: {context}){RESET}")
|
||||
all_valid = False
|
||||
|
||||
if child_id not in self.tenant_data:
|
||||
print(f"{RED}✗ Child tenant {child_id} not found (context: {context}){RESET}")
|
||||
all_valid = False
|
||||
|
||||
# Validate product-tenant relationships
|
||||
if "product_tenant" in self.references:
|
||||
print(f"\n{YELLOW}Validating Product-Tenant relationships...{RESET}")
|
||||
for ref in self.references["product_tenant"]:
|
||||
product_id = ref["product_id"]
|
||||
tenant_id = ref["tenant_id"]
|
||||
context = ref["context"]
|
||||
|
||||
if product_id not in self.product_data:
|
||||
print(f"{RED}✗ Product {product_id} referenced but not found (context: {context}){RESET}")
|
||||
all_valid = False
|
||||
|
||||
if tenant_id not in self.tenant_data:
|
||||
print(f"{RED}✗ Tenant {tenant_id} referenced by product {product_id} but not found (context: {context}){RESET}")
|
||||
all_valid = False
|
||||
|
||||
# Validate product-user relationships
|
||||
if "product_user" in self.references:
|
||||
print(f"\n{YELLOW}Validating Product-User relationships...{RESET}")
|
||||
for ref in self.references["product_user"]:
|
||||
product_id = ref["product_id"]
|
||||
user_id = ref["user_id"]
|
||||
context = ref["context"]
|
||||
|
||||
if product_id not in self.product_data:
|
||||
print(f"{RED}✗ Product {product_id} referenced but not found (context: {context}){RESET}")
|
||||
all_valid = False
|
||||
|
||||
if user_id not in self.user_data:
|
||||
print(f"{RED}✗ User {user_id} referenced by product {product_id} but not found (context: {context}){RESET}")
|
||||
all_valid = False
|
||||
|
||||
# Validate ingredient-tenant relationships
|
||||
if "ingredient_tenant" in self.references:
|
||||
print(f"\n{YELLOW}Validating Ingredient-Tenant relationships...{RESET}")
|
||||
for ref in self.references["ingredient_tenant"]:
|
||||
ingredient_id = ref["ingredient_id"]
|
||||
tenant_id = ref["tenant_id"]
|
||||
context = ref["context"]
|
||||
|
||||
if ingredient_id not in self.product_data:
|
||||
print(f"{RED}✗ Ingredient {ingredient_id} referenced but not found (context: {context}){RESET}")
|
||||
all_valid = False
|
||||
|
||||
if tenant_id not in self.tenant_data:
|
||||
print(f"{RED}✗ Tenant {tenant_id} referenced by ingredient {ingredient_id} but not found (context: {context}){RESET}")
|
||||
all_valid = False
|
||||
|
||||
# Validate ingredient-user relationships
|
||||
if "ingredient_user" in self.references:
|
||||
print(f"\n{YELLOW}Validating Ingredient-User relationships...{RESET}")
|
||||
for ref in self.references["ingredient_user"]:
|
||||
ingredient_id = ref["ingredient_id"]
|
||||
user_id = ref["user_id"]
|
||||
context = ref["context"]
|
||||
|
||||
if ingredient_id not in self.product_data:
|
||||
print(f"{RED}✗ Ingredient {ingredient_id} referenced but not found (context: {context}){RESET}")
|
||||
all_valid = False
|
||||
|
||||
if user_id not in self.user_data:
|
||||
print(f"{RED}✗ User {user_id} referenced by ingredient {ingredient_id} but not found (context: {context}){RESET}")
|
||||
all_valid = False
|
||||
|
||||
# Validate recipe-tenant relationships
|
||||
if "recipe_tenant" in self.references:
|
||||
print(f"\n{YELLOW}Validating Recipe-Tenant relationships...{RESET}")
|
||||
for ref in self.references["recipe_tenant"]:
|
||||
recipe_id = ref["recipe_id"]
|
||||
tenant_id = ref["tenant_id"]
|
||||
context = ref["context"]
|
||||
|
||||
if recipe_id not in self.recipe_data:
|
||||
print(f"{RED}✗ Recipe {recipe_id} referenced but not found (context: {context}){RESET}")
|
||||
all_valid = False
|
||||
|
||||
if tenant_id not in self.tenant_data:
|
||||
print(f"{RED}✗ Tenant {tenant_id} referenced by recipe {recipe_id} but not found (context: {context}){RESET}")
|
||||
all_valid = False
|
||||
|
||||
# Validate recipe-product relationships
|
||||
if "recipe_product" in self.references:
|
||||
print(f"\n{YELLOW}Validating Recipe-Product relationships...{RESET}")
|
||||
for ref in self.references["recipe_product"]:
|
||||
recipe_id = ref["recipe_id"]
|
||||
product_id = ref["product_id"]
|
||||
context = ref["context"]
|
||||
|
||||
if recipe_id not in self.recipe_data:
|
||||
print(f"{RED}✗ Recipe {recipe_id} referenced but not found (context: {context}){RESET}")
|
||||
all_valid = False
|
||||
|
||||
if product_id not in self.product_data:
|
||||
print(f"{RED}✗ Product {product_id} referenced by recipe {recipe_id} but not found (context: {context}){RESET}")
|
||||
all_valid = False
|
||||
|
||||
# Validate supplier-tenant relationships
|
||||
if "supplier_tenant" in self.references:
|
||||
print(f"\n{YELLOW}Validating Supplier-Tenant relationships...{RESET}")
|
||||
for ref in self.references["supplier_tenant"]:
|
||||
supplier_id = ref["supplier_id"]
|
||||
tenant_id = ref["tenant_id"]
|
||||
context = ref["context"]
|
||||
|
||||
if supplier_id not in self.supplier_data:
|
||||
print(f"{RED}✗ Supplier {supplier_id} referenced but not found (context: {context}){RESET}")
|
||||
all_valid = False
|
||||
|
||||
if tenant_id not in self.tenant_data:
|
||||
print(f"{RED}✗ Tenant {tenant_id} referenced by supplier {supplier_id} but not found (context: {context}){RESET}")
|
||||
all_valid = False
|
||||
|
||||
# Validate UUID format for all IDs
|
||||
print(f"\n{YELLOW}Validating UUID formats...{RESET}")
|
||||
for entity_type, ids in self.all_ids.items():
|
||||
for entity_id in ids:
|
||||
try:
|
||||
uuid.UUID(entity_id)
|
||||
except ValueError:
|
||||
print(f"{RED}✗ Invalid UUID format for {entity_type} ID: {entity_id}{RESET}")
|
||||
all_valid = False
|
||||
|
||||
# Check for duplicate IDs
|
||||
print(f"\n{YELLOW}Checking for duplicate IDs...{RESET}")
|
||||
all_entities = []
|
||||
for ids in self.all_ids.values():
|
||||
all_entities.extend(ids)
|
||||
|
||||
duplicates = [id for id in all_entities if all_entities.count(id) > 1]
|
||||
if duplicates:
|
||||
print(f"{RED}✗ Found duplicate IDs: {', '.join(duplicates)}{RESET}")
|
||||
all_valid = False
|
||||
|
||||
if all_valid:
|
||||
print(f"{GREEN}✓ All cross-references are valid!{RESET}")
|
||||
else:
|
||||
print(f"{RED}✗ Found validation errors!{RESET}")
|
||||
|
||||
return all_valid
|
||||
|
||||
def generate_summary(self) -> None:
|
||||
"""Generate a summary of the loaded fixtures"""
|
||||
print(f"\n{BLUE}=== Fixture Summary ==={RESET}")
|
||||
print(f"Tenants: {len(self.tenant_data)}")
|
||||
print(f"Users: {len(self.user_data)}")
|
||||
print(f"Products: {len(self.product_data)}")
|
||||
print(f"Suppliers: {len(self.supplier_data)}")
|
||||
print(f"Recipes: {len(self.recipe_data)}")
|
||||
print(f"Locations: {len(self.location_data)}")
|
||||
|
||||
print(f"\nEntity Types: {list(self.all_ids.keys())}")
|
||||
|
||||
for entity_type, ids in self.all_ids.items():
|
||||
print(f" {entity_type}: {len(ids)} IDs")
|
||||
|
||||
print(f"\nReference Types: {list(self.references.keys())}")
|
||||
for ref_type, refs in self.references.items():
|
||||
print(f" {ref_type}: {len(refs)} references")
|
||||
|
||||
def run_validation(self) -> bool:
|
||||
"""Run the complete validation process"""
|
||||
print(f"{BLUE}=== Enterprise Demo Fixtures Validator ==={RESET}")
|
||||
print(f"Base Path: {self.base_path}\n")
|
||||
|
||||
try:
|
||||
self.load_all_fixtures()
|
||||
self.generate_summary()
|
||||
return self.validate_all_references()
|
||||
|
||||
except Exception as e:
|
||||
print(f"{RED}✗ Validation failed with error: {e}{RESET}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
validator = FixtureValidator()
|
||||
success = validator.run_validation()
|
||||
|
||||
if success:
|
||||
print(f"\n{GREEN}=== Validation Complete: All checks passed! ==={RESET}")
|
||||
sys.exit(0)
|
||||
else:
|
||||
print(f"\n{RED}=== Validation Complete: Errors found! ==={RESET}")
|
||||
sys.exit(1)
|
||||
Reference in New Issue
Block a user