from app import db import datetime import time import json from werkzeug.security import generate_password_hash, check_password_hash # Machine Model class Machine(db.Model): __tablename__ = 'machines' id = db.Column(db.Integer, primary_key=True) machine_id = db.Column(db.String(10), unique=True, nullable=False) machine_model = db.Column(db.String(100), nullable=False) machine_type = db.Column(db.String(100), nullable=False) client_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False) client_name = db.Column(db.String(100), nullable=True) branch_id = db.Column(db.String(10), nullable=False) branch_name = db.Column(db.String(100), nullable=False) operation_status = db.Column(db.String(50), nullable=False) connection_status = db.Column(db.String(50), nullable=False) created_on = db.Column(db.String(20), nullable=False) password = db.Column(db.String(128), nullable=False) slots = db.relationship('VendingSlot', backref='machine', lazy=True) client = db.relationship('User', backref='machines') def to_dict(self): return { 'id': self.id, 'machine_id': self.machine_id, 'machine_model': self.machine_model, 'machine_type': self.machine_type, 'client_id': self.client_id, 'client_name': self.client.username if self.client else self.client_name, 'branch_id': self.branch_id, 'branch_name': self.branch_name, 'operation_status': self.operation_status, 'connection_status': self.connection_status, 'created_on': self.created_on, 'password': self.password } def set_password(self, password): self.password = generate_password_hash(password) def check_password(self, password): return check_password_hash(self.password, password) # User Model - UPDATED with proper password hashing class User(db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.String(50), unique=True, nullable=False) username = db.Column(db.String(50), nullable=False) email = db.Column(db.String(100), nullable=False, unique=True) contact = db.Column(db.String(20), nullable=False) roles = db.Column(db.String(50), nullable=False) user_status = db.Column(db.String(50), nullable=False) password = db.Column(db.String(255), nullable=False) # Increased length for hash # File storage fields photo = db.Column(db.String(255), nullable=True) company_logo = db.Column(db.String(255), nullable=True) documents = db.Column(db.Text, nullable=True) # Timestamps created_at = db.Column(db.DateTime, default=datetime.datetime.utcnow) updated_at = db.Column(db.DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow) def to_dict(self): """Convert user object to dictionary""" return { 'id': self.id, 'user_id': self.user_id, 'username': self.username, 'email': self.email, 'contact': self.contact, 'roles': self.roles, 'user_status': self.user_status, 'photo': self.photo, 'company_logo': self.company_logo, 'documents': json.loads(self.documents) if self.documents else [], 'created_at': self.created_at.strftime("%Y-%m-%d %H:%M:%S") if self.created_at else None, 'updated_at': self.updated_at.strftime("%Y-%m-%d %H:%M:%S") if self.updated_at else None, 'machines': [m.to_dict() for m in self.machines] if hasattr(self, 'machines') else [] } def set_password(self, password): """Hash and set the password""" self.password = generate_password_hash(password, method='pbkdf2:sha256') print(f"Password hashed for user {self.username}") def check_password(self, password): """Verify password against hash""" result = check_password_hash(self.password, password) print(f"Password check for {self.username}: {result}") return result @staticmethod def generate_user_id(username, email): """Generate unique user ID from username and email""" username_part = ''.join(filter(str.isalnum, username[:4])).upper() email_part = ''.join(filter(str.isalnum, email.split('@')[0][:4])).upper() timestamp = str(int(time.time()))[-4:] user_id = f"USR-{username_part}{email_part}{timestamp}" # Ensure uniqueness counter = 1 original_id = user_id while User.query.filter_by(user_id=user_id).first(): user_id = f"{original_id}{counter}" counter += 1 return user_id # Product Model class Product(db.Model): __tablename__ = 'products' id = db.Column(db.Integer, primary_key=True) product_id = db.Column(db.String(10), unique=True, nullable=False) product_name = db.Column(db.String(100), nullable=False) price = db.Column(db.Float, nullable=False) product_image = db.Column(db.String(255), nullable=False) created_date = db.Column(db.String(20), nullable=False) def to_dict(self): return { 'id': self.id, 'product_id': self.product_id, 'product_name': self.product_name, 'price': str(self.price), 'product_image': self.product_image, 'created_date': self.created_date } # VendingSlot Model class VendingSlot(db.Model): __tablename__ = 'vending_slots' id = db.Column(db.Integer, primary_key=True) machine_id = db.Column(db.String(10), db.ForeignKey('machines.machine_id'), nullable=False) row_id = db.Column(db.String(1), nullable=False) slot_name = db.Column(db.String(3), nullable=False) enabled = db.Column(db.Boolean, default=True) product_id = db.Column(db.String(10), db.ForeignKey('products.product_id'), nullable=True) units = db.Column(db.Integer, default=0) price = db.Column(db.String(10), default="N/A") def to_dict(self): return { 'name': self.slot_name, 'enabled': self.enabled, 'productId': self.product_id, 'units': self.units, 'price': self.price } # Transaction Model class Transaction(db.Model): __tablename__ = 'transactions' id = db.Column(db.Integer, primary_key=True) transaction_id = db.Column(db.String(50), unique=True, nullable=False) machine_id = db.Column(db.String(10), db.ForeignKey('machines.machine_id'), nullable=False) product_name = db.Column(db.String(100), nullable=False) quantity = db.Column(db.Integer, nullable=False) amount = db.Column(db.Float, nullable=False) payment_type = db.Column(db.String(50), nullable=False) # wallet/qr/card status = db.Column(db.String(50), nullable=False) # Success/Dispense failed/Unprocessed amount_receiving_status = db.Column(db.String(50), nullable=True) # Dispense failed refund return_amount = db.Column(db.Float, nullable=True) created_at = db.Column(db.DateTime, default=datetime.datetime.utcnow) machine = db.relationship('Machine', backref='transactions') def to_dict(self): return { 'id': self.id, 'transaction_id': self.transaction_id, 'machine_id': self.machine_id, 'product_name': self.product_name, 'quantity': self.quantity, 'amount': self.amount, 'payment_type': self.payment_type, 'status': self.status, 'amount_receiving_status': self.amount_receiving_status, 'return_amount': self.return_amount, 'created_at': self.created_at.strftime("%Y-%m-%d %H:%M:%S") if self.created_at else None } # Add to your models.py class Role(db.Model): __tablename__ = 'roles' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50), unique=True, nullable=False) description = db.Column(db.String(255)) permissions = db.Column(db.Text) # JSON string of permission IDs created_at = db.Column(db.DateTime, default=datetime.datetime.utcnow) updated_at = db.Column(db.DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow) def to_dict(self): return { 'id': self.id, 'name': self.name, 'description': self.description, 'permissions': json.loads(self.permissions) if self.permissions else [], 'created_at': self.created_at.strftime("%Y-%m-%d %H:%M:%S") if self.created_at else None, 'updated_at': self.updated_at.strftime("%Y-%m-%d %H:%M:%S") if self.updated_at else None }