""" SQLite Data Access Layer Provides database operations using SQLAlchemy """ from models import db, User, Product, Location, ProductAttribute from werkzeug.security import generate_password_hash # ============================================================================ # USER OPERATIONS # ============================================================================ def get_user_by_username(username): """Get a user by username""" return User.query.filter_by(username=username).first() def get_user_by_id(user_id): """Get a user by ID""" return User.query.get(user_id) def get_all_users(): """Get all users""" users = User.query.all() return [user.to_dict() for user in users] def create_user(user_data): """ Create a new user Args: user_data (dict): User data with keys: username, password, defaultLocation, locationSettings, permissions, active Returns: dict: Created user as dictionary or None if username exists """ # Check if username already exists if User.query.filter_by(username=user_data['username']).first(): return None # Hash password if not already hashed password = user_data['password'] if not password.startswith('pbkdf2:'): password = generate_password_hash(password, method='pbkdf2:sha256') # Get location settings location_settings = user_data.get('locationSettings', {}) default_location = user_data['defaultLocation'] # Ensure default location is accessible if default_location not in location_settings: location_settings[default_location] = {} location_settings[default_location]['accessible'] = True # Create user user = User( username=user_data['username'], password=password, default_location=default_location, active=user_data.get('active', True), super_admin=user_data.get('superAdmin', False) ) user.locationSettings = location_settings user.permissions = user_data.get('permissions', {}) db.session.add(user) db.session.commit() return user.to_dict() def update_user(user_id, user_data): """ Update an existing user Args: user_id (int): User ID user_data (dict): Updated user data Returns: dict: Updated user as dictionary or None if not found """ user = User.query.get(user_id) if not user: return None # Update fields if 'defaultLocation' in user_data: user.default_location = user_data['defaultLocation'] if 'active' in user_data: user.active = user_data['active'] if 'superAdmin' in user_data: user.super_admin = user_data['superAdmin'] if 'locationSettings' in user_data: user.locationSettings = user_data['locationSettings'] if 'permissions' in user_data: user.permissions = user_data['permissions'] if 'password' in user_data: password = user_data['password'] if not password.startswith('pbkdf2:'): password = generate_password_hash(password, method='pbkdf2:sha256') user.password = password db.session.commit() return user.to_dict() def delete_user(user_id): """ Delete a user Args: user_id (int): User ID Returns: bool: True if deleted, False if not found """ user = User.query.get(user_id) if not user: return False db.session.delete(user) db.session.commit() return True def toggle_user_active(user_id, active): """ Toggle user active status Args: user_id (int): User ID active (bool): Active status Returns: dict: Updated user or None if not found """ user = User.query.get(user_id) if not user: return None user.active = active db.session.commit() return user.to_dict() def change_user_password(user_id, new_password): """ Change a user's password Args: user_id (int): User ID new_password (str): New password (will be hashed) Returns: dict: Updated user or None if not found """ user = User.query.get(user_id) if not user: return None hashed_password = generate_password_hash(new_password, method='pbkdf2:sha256') user.password = hashed_password db.session.commit() return user.to_dict() # ============================================================================ # PRODUCT OPERATIONS # ============================================================================ def get_all_products(location=None): """ Get all products, optionally filtered by location Args: location (str, optional): Filter by location code Returns: list: List of product dictionaries """ query = Product.query if location: query = query.filter_by(location=location) products = query.all() return [product.to_dict() for product in products] def get_product_by_code(product_code): """ Get a product by its product code Args: product_code (str): Product code Returns: dict: Product dictionary or None if not found """ product = Product.query.filter_by(product_code=product_code).first() return product.to_dict() if product else None def create_product(product_data): """ Create a new product Args: product_data (dict): Product data Returns: dict: Created product or None if code exists """ # Check if product already exists if Product.query.filter_by(product_code=product_data['productCode']).first(): return None # Create product product = Product( product_code=product_data['productCode'], category=product_data.get('category'), description=product_data.get('description'), discontinued=product_data.get('discontinued', False), location=product_data.get('location'), base_type=product_data.get('baseType', ''), is_accessory=product_data.get('isAccessory', False) ) # Set JSON properties product.subType = product_data.get('subType', {}) product.materials = product_data.get('materials', []) product.colors = product_data.get('colors', []) product.compatibleAccessories = product_data.get('compatibleAccessories', []) product.imageConfig = product_data.get('imageConfig', {}) db.session.add(product) db.session.commit() return product.to_dict() def update_product(product_code, product_data): """ Update an existing product Args: product_code (str): Product code product_data (dict): Updated product data Returns: dict: Updated product or None if not found """ product = Product.query.filter_by(product_code=product_code).first() if not product: return None # Update fields if 'category' in product_data: product.category = product_data['category'] if 'description' in product_data: product.description = product_data['description'] if 'discontinued' in product_data: product.discontinued = product_data['discontinued'] if 'location' in product_data: product.location = product_data['location'] if 'baseType' in product_data: product.base_type = product_data['baseType'] if 'isAccessory' in product_data: product.is_accessory = product_data['isAccessory'] # Update JSON properties if 'subType' in product_data: product.subType = product_data['subType'] if 'materials' in product_data: product.materials = product_data['materials'] if 'colors' in product_data: product.colors = product_data['colors'] if 'compatibleAccessories' in product_data: product.compatibleAccessories = product_data['compatibleAccessories'] if 'imageConfig' in product_data: product.imageConfig = product_data['imageConfig'] db.session.commit() return product.to_dict() def delete_product(product_code): """ Delete a product Args: product_code (str): Product code Returns: bool: True if deleted, False if not found """ product = Product.query.filter_by(product_code=product_code).first() if not product: return False db.session.delete(product) db.session.commit() return True # ============================================================================ # LOCATION OPERATIONS # ============================================================================ def get_all_locations(): """Get all locations""" locations = Location.query.filter_by(active=True).all() return [loc.to_dict() for loc in locations] def get_location_by_code(code): """Get a location by code""" location = Location.query.filter_by(code=code).first() return location.to_dict() if location else None # ============================================================================ # PRODUCT ATTRIBUTES OPERATIONS # ============================================================================ def get_product_attributes(): """ Get product attributes configuration Returns: dict: Attributes with locations, statuses, productTypes, codeModifiers """ attributes = ProductAttribute.query.first() if not attributes: return { 'locations': get_all_locations(), 'statuses': [], 'productTypes': [], 'codeModifiers': [] } return attributes.to_dict() def update_product_attributes(attributes_data): """ Update product attributes configuration Args: attributes_data (dict): Updated attributes Returns: dict: Updated attributes """ attributes = ProductAttribute.query.first() if not attributes: attributes = ProductAttribute() db.session.add(attributes) if 'statuses' in attributes_data: attributes.statuses = attributes_data['statuses'] if 'productTypes' in attributes_data: attributes.productTypes = attributes_data['productTypes'] if 'codeModifiers' in attributes_data: attributes.codeModifiers = attributes_data['codeModifiers'] db.session.commit() return attributes.to_dict() # ============================================================================ # UTILITY FUNCTIONS # ============================================================================ def commit(): """Commit current transaction""" db.session.commit() def rollback(): """Rollback current transaction""" db.session.rollback()