erdemerikci 45d80dfaa6 Initial import: Lightning_Report with n8n integration
Fork of Lightning_Report adding:
- n8n_report_branch.json: workflow branch for storm-triggered report delivery
- report_service/: FastAPI microservice wrapping create_docx_report() so n8n
  can produce byte-identical reports without fighting the Python Code sandbox

Made-with: Cursor
2026-04-22 15:13:08 +03:00

85 lines
3.1 KiB
Python

import sys
import argparse
import logging
from typing import Any
from src.api.data_fetcher import APIDataFetcher
import batch_generate
# Set up logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.StreamHandler(sys.stdout),
logging.FileHandler('lightning_report.log')
]
)
logger = logging.getLogger(__name__)
def main():
"""Generate DOCX reports (from wind_farms_config.json)."""
try:
parser = argparse.ArgumentParser(description="DOCX lightning report generation (from wind_farms_config.json)")
parser.add_argument("--config", default="wind_farms_config.json", help="Path to wind_farms_config.json")
parser.add_argument("--farm-id", default=None, help="farm_id to process (if omitted, process enabled farms)")
parser.add_argument("--force", action="store_true", help="Process even if farm is disabled")
args = parser.parse_args()
logger.info("Starting DOCX report generation...")
config = batch_generate.load_wind_farms_config(args.config)
farms = config.get("wind_farms", [])
api_cfg = config["api_config"]
api_fetcher = APIDataFetcher(
base_url=api_cfg["base_url"],
timeout=api_cfg.get("timeout_seconds", 30),
retry_attempts=api_cfg.get("retry_attempts", 3),
)
if args.farm_id:
farms_to_process = [f for f in farms if f.get("farm_id") == args.farm_id]
if not farms_to_process:
logger.error(f"Farm '{args.farm_id}' not found in {args.config}")
sys.exit(1)
else:
farms_to_process = farms
results: list[dict[str, Any]] = []
for idx, farm in enumerate(farms_to_process, 1):
farm_id = farm.get("farm_id")
name = farm.get("name", farm_id)
if not args.force and not farm.get("enabled", True):
logger.info(f"[{idx}/{len(farms_to_process)}] Skipping disabled farm: {farm_id} ({name})")
continue
logger.info(f"[{idx}/{len(farms_to_process)}] Processing farm: {farm_id} ({name})")
result = batch_generate.process_farm(farm, api_fetcher, config)
results.append(result)
if result.get("status") != "success":
logger.error(f"Report generation failed for {farm_id}: {result.get('error')}")
# Keep going if doing batch; stop early for single farm.
if args.farm_id:
sys.exit(1)
for r in results:
if r.get("status") == "success":
logger.info(f"✅ DOCX report saved as {r.get('docx_path')}")
logger.info("Lightning report generation completed successfully!")
except FileNotFoundError as e:
logger.error(f"File not found: {e}")
sys.exit(1)
except ValueError as e:
logger.error(f"Data validation error: {e}")
sys.exit(1)
except Exception as e:
logger.error(f"Unexpected error: {e}")
sys.exit(1)
if __name__ == '__main__':
main()