예제 #1
0
파일: mail.py 프로젝트: M0r13n/price_picker
class Mail(CRUDMixin, db.Model):
    __tablename__ = 'mails'
    id = db.Column(db.Integer, primary_key=True)
    mail = db.Column(db.String(200), unique=True, nullable=False)

    def __repr__(self):
        return "<Mail %s>" % self.mail
예제 #2
0
class Picture(db.Model):
    """
    All pictures are stored in a html subpage inside the device_mocks folder.
    There is also a default one.
    """
    __tablename__ = 'pictures'
    name = db.Column(db.String(64), unique=True, primary_key=True, nullable=False)
    filename = db.Column(db.String(128), unique=True, nullable=False)
    default = db.Column(db.Boolean, default=False, index=True)
    manufacturers = db.relationship('Manufacturer', backref='picture')
    devices = db.relationship('Device', backref='picture')

    def __repr__(self):
        return f"<Picture {self.name}@[{self.file}]"

    @classmethod
    def query_factory_all(cls):
        """
        Query Factory for use in sqlalchemy.wtforms
        """
        return cls.query.order_by(cls.name)

    @property
    def dir(self):
        return PICTURE_BASE_PATH

    @property
    def file(self):
        return f"{self.dir}{self.filename}"

    @classmethod
    def default_picture(cls):
        return cls.query.filter_by(default=True).first()

    @staticmethod
    def create_basic_pictures():
        """
        Insert default Pictures and set the default
        :return:
        """
        basics = {
            'htc': '_htc.html',
            'ipad': '_ipad_mini.html',
            'iphone_4s': '_iphone_4s.html',
            'iphone_5s': '_iphone_5s.html',
            'iphone_5c': '_iphone_5c.html',
            'iphone_8': '_iphone_8.html',
            'iphone_8_plus': '_iphone_8_plus.html',
            'iphone_x': '_iphone_x.html',
            'nexus': '_nexus_5.html',
            'note': '_note_8.html',
            's5': '_s5.html',
        }
        Picture.query.delete()
        # set default picture
        default = 'nexus'
        # bulk insert pictures
        pictures = [Picture(name=k, filename=v, default=k == default) for k, v in basics.items()]
        db.session.bulk_save_objects(pictures)
        db.session.commit()
예제 #3
0
class CouponCode(CRUDMixin, db.Model):
    VALUES = [5, 10]

    __tablename__ = 'coupons'
    id = db.Column(db.Integer, primary_key=True)
    code = db.Column(db.String(10), unique=True, nullable=False)
    value = db.Column(db.Integer)

    def __repr__(self):
        return "<Coupon %s>" % self.mail
예제 #4
0
class Repair(db.Model, CRUDMixin):
    """ Repair e.g. display """
    __tablename__ = 'repair'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64))
    price = db.Column(db.Integer, default=0)
    devices = relationship("Device", secondary=repair_association_table, back_populates="repairs", lazy='dynamic')

    def __repr__(self):
        return f"<{self.name} : {self.price}"
예제 #5
0
class Device(db.Model, CRUDMixin):
    """
    Generic Device
    Can be a Smartphone, Tablet or anything else
    """
    __tablename__ = 'devices'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True, index=True)
    manufacturer_id = db.Column(db.Integer, db.ForeignKey('manufacturers.id'))
    manufacturer = relationship('Manufacturer', back_populates='devices')
    repairs = relationship('Repair', secondary=repair_association_table, back_populates='devices', lazy='dynamic')
    picture_id = db.Column(db.String, db.ForeignKey('pictures.name'))
    colors = relationship("Color", secondary=color_association_table)
    enquiries = relationship("Enquiry", back_populates="device")

    def __init__(self, **kwargs):
        super(Device, self).__init__(**kwargs)
        if len(self.colors) == 0:
            default_color = Color.query.filter_by(default=True).first()
            if default_color is not None:
                self.colors.append(default_color)

    def __repr__(self):
        return f"<Device: {self.manufacturer.name} - {self.name}>"

    @property
    def picture_file(self):
        """
        Get the picture file or if none is provided use the manufacturers default
        and if no picture is defined at all it uses the default picture.
        :return: template path of associated html render
        """
        if self.picture is None:
            return self.manufacturer.picture_file
        return self.picture.file

    @classmethod
    def query_factory_all(cls):
        """
        Query Factory for use in sqlalchemy.wtforms
        """
        return cls.query.order_by(cls.name)

    @classmethod
    def _check_if_paths_are_valid(cls):
        """
        private function to ensure every device points to a html render
        :return: True if everything is valid else False
        """
        for d in cls.query.all():
            if d.picture is None or d.picture_file is None:
                return False
        return True
예제 #6
0
class Color(db.Model, CRUDMixin):
    """ Store colors and their associated color codes """
    __tablename__ = 'color'
    name = db.Column(db.String(128), primary_key=True)
    color_code = db.Column(db.String(20))
    default = db.Column(db.Boolean, default=False, index=True)

    @classmethod
    def query_factory_all(cls):
        """
        Query Factory for use in sqlalchemy.wtforms
        """
        return cls.query.order_by(cls.name)

    def __repr__(self):
        return f"<{self.name} : {self.color_code}>"
예제 #7
0
class User(UserMixin, CRUDMixin, db.Model):
    """Basic user model
    """
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    password_hash = db.Column(db.String(255), nullable=False)

    def __repr__(self):
        return "<User %s>" % self.username

    @property
    def password(self):
        raise AttributeError('password is not a readable attribute')

    @password.setter
    def password(self, password):
        self.password_hash = generate_password_hash(password)

    def verify_password(self, password):
        return check_password_hash(self.password_hash, password)
예제 #8
0
class Manufacturer(db.Model, CRUDMixin):
    __tablename__ = 'manufacturers'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True, index=True)
    devices = relationship('Device', back_populates='manufacturer', cascade="all, delete-orphan")
    picture_id = db.Column(db.String, db.ForeignKey('pictures.name'))

    def __init__(self, **kwargs):
        super(Manufacturer, self).__init__(**kwargs)
        if self.picture is None:
            self.picture = Picture.default_picture()

    @property
    def picture_file(self):
        if self.picture is None:
            return Picture.default_picture().file
        return self.picture.file

    @classmethod
    def query_factory_all(cls):
        """
        Query Factory for use in sqlalchemy.wtforms
        """
        return cls.query.order_by(cls.name)
예제 #9
0
class Shop(CRUDMixin, db.Model):
    """ Shops """
    __tablename__ = 'shops'
    name = db.Column(db.String(128), primary_key=True, unique=True, default="Zentrale")

    @classmethod
    def query_factory_all(cls):
        # insert default if no shop exists
        if cls.query.first() is None:
            cls.create()
        return cls.query.order_by(cls.name)

    def __str__(self):
        return self.name

    __repr__ = __str__
예제 #10
0
class Preferences(db.Model, CRUDMixin):
    """ Store User Preferences here"""
    __tablename__ = 'preferences'
    id = db.Column(db.Integer, primary_key=True)
    imei_required = db.Column(db.Boolean, default=False)
    first_name_required = db.Column(db.Boolean, default=False)
    last_name_required = db.Column(db.Boolean, default=False)
    phone_required = db.Column(db.Boolean, default=False)
    mail_required = db.Column(db.Boolean, default=True)
    address_required = db.Column(db.Boolean, default=False)
    phone_number = db.Column(db.String(128))
    mail = db.Column(db.String(128))
    active_sale = db.Column(db.Boolean, default=False)
    sale_amount = db.Column(db.Integer, default=0)

    # Mail Settings
    mail_port = db.Column(db.Integer, default=587)
    mail_server = db.Column(db.String(128))
    mail_encryption = db.Column(db.Integer, default=1)
    mail_username = db.Column(db.String(128))
    mail_default_sender = db.Column(db.String(128))
    mail_password_encrypted = db.Column(db.LargeBinary)
    order_copy_mail_address = db.Column(db.String(128))

    @property
    def mail_password(self):
        raise AttributeError('password is not a readable attribute')

    def encrypt_mail_password(self, password):
        """
        Accepts the clear text password and stores it encrypted with the app´s secret key.

        :param password: clear text password
        :return:
        """
        if not has_app_context:
            raise ValueError("No App Context")
        secret_key = current_app.config['SECRET_KEY']
        cryptor = rncryptor.RNCryptor()
        encrypted_password = cryptor.encrypt(password, secret_key)
        self.mail_password_encrypted = encrypted_password
        db.session.commit()
        current_app.logger.info("Successfully encrypted mail password.")

    def decrypt_mail_password(self):
        """
        Decrypts the encrypted password with the app´s secret key.
        :return: decrypted password
        """
        if not has_app_context:
            raise ValueError("No App Context")
        secret_key = current_app.config['SECRET_KEY']
        cryptor = rncryptor.RNCryptor()
        decrypted_password = cryptor.decrypt(self.mail_password_encrypted,
                                             secret_key)
        current_app.logger.info("Successfully decrypted mail password.")
        return decrypted_password

    @classmethod
    def load_settings(cls):
        """
        Load config into memory
        """
        p = cls.query.first()
        if p is None:
            return
        current_app.config['IMEI_REQUIRED'] = p.imei_required
        current_app.config['FIRST_NAME_REQUIRED'] = p.first_name_required
        current_app.config['LAST_NAME_REQUIRED'] = p.last_name_required
        current_app.config['PHONE_REQUIRED'] = p.phone_required
        current_app.config['MAIL_REQUIRED'] = p.mail_required
        current_app.config['ADDRESS_REQUIRED'] = p.address_required
        current_app.config['USER_MAIL'] = p.mail
        current_app.config['USER_PHONE'] = p.phone_number
        current_app.config['ACTIVE_SALE'] = p.active_sale
        current_app.config['SALE_AMOUNT'] = p.sale_amount

    @property
    def mail_config(self):
        """
        Load mail config settings
        """
        config = {
            'MAIL_USERNAME': self.mail_username,
            'MAIL_PASSWORD': self.decrypt_mail_password(),
            'MAIL_SERVER': self.mail_server,
            'MAIL_USE_TLS': self.mail_encryption == Encryption.TLS,
            'MAIL_USE_SSL': self.mail_encryption == Encryption.SSL,
            'MAIL_DEFAULT_SENDER': self.mail_default_sender
            or self.mail_username,
            'MAIL_PORT': self.mail_port
        }
        return config
예제 #11
0
    @property
    def picture_file(self):
        if self.picture is None:
            return Picture.default_picture().file
        return self.picture.file

    @classmethod
    def query_factory_all(cls):
        """
        Query Factory for use in sqlalchemy.wtforms
        """
        return cls.query.order_by(cls.name)


repair_association_table = db.Table('repair_association',
                                    db.Column('device_id', db.Integer, db.ForeignKey('devices.id', ondelete="cascade")),
                                    db.Column('repair_id', db.Integer, db.ForeignKey('repair.id', ondelete="cascade"))
                                    )

color_association_table = db.Table('color_association',
                                   db.Column('device_id', db.Integer, db.ForeignKey('devices.id', ondelete="cascade")),
                                   db.Column('color_name', db.String, db.ForeignKey('color.name', ondelete="cascade"))
                                   )


class Device(db.Model, CRUDMixin):
    """
    Generic Device
    Can be a Smartphone, Tablet or anything else
    """
    __tablename__ = 'devices'
예제 #12
0
class Enquiry(db.Model, CRUDMixin):
    __tablename__ = "enquiries"
    id = db.Column(db.Integer, primary_key=True)
    timestamp = db.Column(db.DateTime, default=dt.datetime.now)
    name = db.Column(db.String(128))
    customer_first_name = db.Column(db.String(128))
    customer_last_name = db.Column(db.String(128))
    customer_email = db.Column(db.String(128))
    customer_phone = db.Column(db.String(128))
    customer_street = db.Column(db.String(128))
    customer_city = db.Column(db.String(128))
    customer_postal_code = db.Column(db.String(32))
    sale = db.Column(db.Integer, default=0)
    imei = db.Column(db.String(64))
    color = db.Column(db.String(64))
    shop = db.Column(db.String(128))
    device_id = db.Column(db.Integer, db.ForeignKey('devices.id'))
    device = relationship("Device", back_populates="enquiries")
    repairs = relationship("Repair", secondary=repairs)
    done = db.Column(db.Boolean, default=False)

    def __repr__(self):
        return f"<Enquiry ({self.name}) from {self.timestamp.strftime('%d.%m.%Y at %H:%M')}>"

    @property
    def address(self):
        return f"{self.customer_street or '-'}, {self.customer_postal_code or '-'}, {self.customer_street or '-'}"
예제 #13
0
from price_picker import db
import datetime as dt
from sqlalchemy.orm import relationship
from price_picker.common.database import CRUDMixin

repairs = db.Table(
    'repairs',
    db.Column('repair_id', db.Integer,
              db.ForeignKey('repair.id', ondelete="cascade")),
    db.Column('enquiry_id', db.Integer,
              db.ForeignKey('enquiries.id', ondelete="cascade")))


class Enquiry(db.Model, CRUDMixin):
    __tablename__ = "enquiries"
    id = db.Column(db.Integer, primary_key=True)
    timestamp = db.Column(db.DateTime, default=dt.datetime.now)
    name = db.Column(db.String(128))
    customer_first_name = db.Column(db.String(128))
    customer_last_name = db.Column(db.String(128))
    customer_email = db.Column(db.String(128))
    customer_phone = db.Column(db.String(128))
    customer_street = db.Column(db.String(128))
    customer_city = db.Column(db.String(128))
    customer_postal_code = db.Column(db.String(32))
    sale = db.Column(db.Integer, default=0)
    imei = db.Column(db.String(64))
    color = db.Column(db.String(64))
    shop = db.Column(db.String(128))
    device_id = db.Column(db.Integer, db.ForeignKey('devices.id'))
    device = relationship("Device", back_populates="enquiries")