import os from flask import Flask, send_from_directory from flask_cors import CORS from flask_sqlalchemy import SQLAlchemy from dotenv import load_dotenv load_dotenv() db = SQLAlchemy() def create_app(): app = Flask(__name__, instance_relative_config=True) # CORS Configuration CORS(app, resources={ r"/*": { "origins": ["http://localhost:4200", "http://localhost:4300"], "methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"], "allow_headers": ["Content-Type", "Authorization"], "supports_credentials": True } }) # Ensure directories exist instance_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'instance')) uploads_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'Uploads')) for path in [instance_path, uploads_path]: if not os.path.exists(path): os.makedirs(path) app.config['UPLOAD_FOLDER'] = uploads_path # Database configuration flask_env = os.getenv('FLASK_ENV', 'development').lower() if flask_env == 'production': mysql_host = os.getenv('MYSQL_HOST') mysql_user = os.getenv('MYSQL_USER') mysql_password = os.getenv('MYSQL_PASSWORD') mysql_db = os.getenv('MYSQL_DATABASE') if not all([mysql_host, mysql_user, mysql_password, mysql_db]): raise ValueError("Missing required MySQL environment variables") app.config['SQLALCHEMY_DATABASE_URI'] = ( f'mysql+pymysql://{mysql_user}:{mysql_password}@{mysql_host}:3306/{mysql_db}' ) else: sqlite_db_path = os.getenv('SQLITE_DB_PATH', 'machines.db') db_path = os.path.join(instance_path, sqlite_db_path) app.config['SQLALCHEMY_DATABASE_URI'] = f'sqlite:///{db_path}' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False app.config['SQLALCHEMY_ECHO'] = os.getenv('SQLALCHEMY_ECHO', 'False').lower() == 'true' # Initialize extensions db.init_app(app) # Import models from app.models.models import Machine, User, Product, VendingSlot, Transaction # Create tables with app.app_context(): db.create_all() print(f"✓ Database initialized ({flask_env})") # FIXED: Serial service connection BEFORE return from app.services.services import serial_service try: connected = serial_service.connect_to_machine('/dev/ttyUSB0', 9600) if connected: print("✓ Vending machine connected successfully") else: print("✗ Failed to connect to vending machine") except Exception as e: print(f"⚠ Serial connection error: {e}") # Register blueprints from app.routes.routes import bp app.register_blueprint(bp, url_prefix='/') @app.route('/uploads/') def uploaded_file(filename): return send_from_directory(app.config['UPLOAD_FOLDER'], filename) return app