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,","https://shop.rootxwire.com/"], "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") # FIXED: Use port 3306 (internal Docker port, not the host port 3307) 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})") # OPTIONAL: Serial service connection (non-blocking) # Only attempt connection if ENABLE_SERIAL is set to true if os.getenv('ENABLE_SERIAL', 'false').lower() == 'true': 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("⚠ Vending machine not connected (device may not be available)") except Exception as e: print(f"⚠ Serial connection skipped: {e}") else: print("ℹ Serial connection disabled (set ENABLE_SERIAL=true to enable)") # 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