class Promocode(TimedBaseModel):
    __tablename__ = "promocodes_to_customers"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    customer_id = db.Column(db.BigInteger,
                            db.ForeignKey('customers.id'),
                            nullable=False)
    pormocode_id = db.Column(db.Integer,
                             db.ForeignKey('pormocodes.id'),
                             nullable=False)
    product_id = db.Column(db.Integer,
                           db.ForeignKey('products.id'),
                           nullable=True)
    day_expire = db.Column(db.Integer, default=7)
    start = db.Column(db.Date, default='2020-01-01')
    finish = db.Column(db.Date, default='2099-12-31')
    discount_percent = db.Column(db.Integer, nullable=True)
    discount_amount = db.Column(db.Integer, nullable=True)

    query: sql.Select

    @classmethod
    async def get(cls, code: str):
        item = await cls.query.where(cls.code == code.upper()).gino.first()
        return item
Beispiel #2
0
class Payment(TimedBaseModel):
    __tablename__ = 'payments'

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    customer_id = db.Column(db.BigInteger, db.ForeignKey('customers.id'), nullable=False)
    order_id = db.Column(db.Integer, db.ForeignKey('orders.id'), nullable=True)
    entity_type_id = db.Column(db.Integer, db.ForeignKey('entities_types.id'), nullable=True)
    payments_sum = db.Column(db.Integer)

    query: sql.Select
Beispiel #3
0
class Bill(TimedBaseModel):
    __tablename__ = "bills"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    uid = db.Column(db.String(36), unique=True)
    customer_id = db.Column(db.BigInteger, db.ForeignKey("customers.id"))
    order_id = db.Column(db.Integer, db.ForeignKey("orders.id"))
    amount = db.Column(db.Integer)
    status_id = db.Column(db.Integer, db.ForeignKey("statuses.id"))
    date_expire = db.Column(db.TIMESTAMP)
    comment = db.Column(db.String(255), default='')

    query: sql.Select

    @classmethod
    async def add(cls, order: Order, minutes=10, comment=''):
        try:
            if order.total >= 1:
                uid = str(uuid.uuid4())

                date_expire = datetime.now() + timedelta(minutes=minutes)

                if not comment:
                    comment = f"Заказ #{order.id}"

                obj = Bill(uid=uid, customer_id=order.customer_id, order_id=order.id, amount=order.total,
                           status_id=1, date_expire=date_expire, comment=comment)
                await obj.create()
                return obj
        except UniqueViolationError:
            pass

    @classmethod
    async def get_or_add(cls, order: Order, minutes=10, comment=''):
        obj = await cls.get(order)
        if not obj:
            obj = await cls.add(order=order, minutes=minutes, comment=comment)
        return obj

    @classmethod
    async def get(cls, order: Order):
        obj = await cls.query.where(
            and_(
                cls.order_id == order.id,
                cls.date_expire < datetime.utcnow()
            )
        ).gino.first()

        return obj
Beispiel #4
0
class File(TimedBaseModel):
    __tablename__ = 'files'

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    customer_id = db.Column(db.BigInteger,
                            db.ForeignKey('customers.id'),
                            nullable=False)
    file_key = db.Column(db.String, unique=True, nullable=False)
    mime_type = db.Column(db.String, nullable=False, default='')

    query: sql.Select

    @classmethod
    async def add(cls,
                  customer_id: customer_id,
                  file_name: str,
                  file_unique_id,
                  mime_type: str = None,
                  file_prefix: str = ''):
        try:

            file_extension = mimetypes.guess_extension(mime_type)
            file_key = f"{file_prefix}{customer_id}/{file_unique_id}{file_extension}"

            obj = await cls.query.where(cls.file_key == file_key).gino.first()
            if not obj:
                s3_client.upload_file(file_name, S3_BUCKET, file_key)
                obj = cls(customer_id=customer_id,
                          file_key=file_key,
                          mime_type=mime_type)
                await obj.create()
        except UniqueViolationError:
            obj = await cls.query.where(cls.file_key == file_key).gino.first()

        return obj
Beispiel #5
0
class EntityType(BaseModel):
    __tablename__ = "entities_types"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    code = db.Column(db.String(50), unique=True)
    entity_id = db.Column(db.Integer,
                          db.ForeignKey('entities.id'),
                          nullable=False)
    name = db.Column(db.String(150), unique=False)

    @classmethod
    async def add(cls, code: str, name: str = '', entity_id: int = 0):
        try:
            obj = cls(code=code, name=name, entity_id=entity_id)
            await obj.create()
        except UniqueViolationError:
            pass

    @classmethod
    async def get(cls, code: str):
        item = await cls.query.where(cls.code == code.lower()).gino.first()
        return item

    @classmethod
    async def get_all(cls, entity_id: int = 0):
        if entity_id:
            items = await cls.query.where(cls.entity_id == entity_id
                                          ).gino.all()
        else:
            items = await cls.query.where().gino.all()
        return items
Beispiel #6
0
class Document(TimedBaseModel):
    __tablename__ = "documents"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    customer_id = db.Column(db.BigInteger, db.ForeignKey('customers.id'))

    fio = db.Column(db.String)
    birthday = db.Column(db.Date)
    entity_type_id = db.Column(db.Integer, db.ForeignKey('entities_types.id'))
    number = db.Column(db.String)

    issued_code = db.Column(db.String)
    issued_by = db.Column(db.String)
    issued_date = db.Column(db.Date)

    registration_address = db.Column(db.String)

    foto_main = db.Column(db.String)
    foto_registration = db.Column(db.String)
Beispiel #7
0
class Weight(db.Model):
    __tablename__ = 'weight'
    query: sql.Select

    id = db.Column(db.Integer, primary_key=True)
    user_weight = db.Column(db.String(10))
    date_of_update = db.Column(DateTime, default=datetime.utcnow)
    users_id = db.Column(db.Integer, db.ForeignKey('users.user_tg_id'))

    def __repr__(self):
        return f'''
Beispiel #8
0
class Phone(TimedBaseModel):
    __tablename__ = "phones"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    customer_id = db.Column(db.BigInteger, db.ForeignKey('customers.id'))

    source_number = db.Column(db.String(150))
    number = db.Column(db.String(50))
    region = db.Column(db.String(100))
    operator = db.Column(db.String(50))
    old_operator = db.Column(db.String(50))

    @classmethod
    async def add(cls, customer_id: int, source_number: str):
        import requests
        from phonenumbers import parse
        try:
            phone_obj = parse(number=source_number, region="RU")
        except NumberParseException.NOT_A_NUMBER:
            return {
                'info':
                f"Неверный формат номера: <pre>{source_number}</pre>",
                'example':
                ["+74959898533", "74959898533", "84959898533", "4959898533"]
            }

        url = "http://num.voxlink.ru/get/"

        querystring = {
            "num": f"+{phone_obj.country_code}{phone_obj.national_number}"
        }

        payload = ""
        response = requests.request("GET",
                                    url,
                                    data=payload,
                                    params=querystring)
        phone_obj = json.loads(response.text)

        if phone_obj.get('info'):
            return phone_obj.get('info',
                                 '') + " - разрешенный формат: " + ", ".join(
                                     phone_obj.get('example', ''))
        else:
            obj = cls(customer_id=customer_id,
                      source_number=source_number,
                      number=phone_obj.get('full_num'),
                      region=phone_obj.get('region'),
                      operator=phone_obj.get('operator'),
                      old_operator=phone_obj.get('old_operator'))
            await obj.create()
Beispiel #9
0
class Custumer(TimedBaseModel):
    __tablename__ = 'customers'

    id = db.Column(BigInteger, primary_key=True)
    name = db.Column(String(200))
    status_id = db.Column(db.Integer,
                          db.ForeignKey('statuses.id'),
                          nullable=False)
    referral_id = db.Column(db.BigInteger, default=0)
    is_admin = db.Column(db.Boolean, default=False)
    is_manager = db.Column(db.Boolean, default=False)
    is_supplier = db.Column(db.Boolean, default=False)

    query: sql.Select
Beispiel #10
0
class Order(TimedBaseModel):
    __tablename__ = 'orders'

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    customer_id = db.Column(db.BigInteger,
                            db.ForeignKey('customers.id'),
                            nullable=False)
    status_id = db.Column(db.Integer,
                          db.ForeignKey('statuses.id'),
                          nullable=False)
    discount_percent = db.Column(db.Integer, default=0)

    subtotal = db.Column(db.Integer, default=0)
    customer_discount = db.Column(db.Integer, default=0)
    promocode_discount = db.Column(db.Integer, default=0)
    bonuses = db.Column(db.Integer, default=0)
    noncash = db.Column(db.Integer, default=0)
    total = db.Column(db.Integer, default=0)

    comment = db.Column(db.String(255), default='')

    query: sql.Select

    async def add_product(self, product: Product, price: int):
        try:
            from utils.db_api.models.orders_lines import OrderLine
            await OrderLine.add(order=self,
                                product=product,
                                price=price,
                                quantity=1)
            await self.recalculate()
            return self
        except UniqueViolationError:
            pass

    async def recalculate(self):
        from utils.db_api.models.orders_lines import OrderLine
        items = await OrderLine.query.where(OrderLine.order_id == self.id
                                            ).gino.all()
        subtotal = 0
        customer_discount = 0
        promocode_discount = 0
        bonuses = 0
        noncash = 0

        self_update = {}

        for item in items:
            item_update = dict()
            if item.deleted_at:
                if not item.customer_discount == 0:
                    item_update.update({'customer_discount': 0})
                if not item.promocode_discount == 0:
                    item_update.update({'promocode_discount': 0})
                if not item.bonuses == 0:
                    item_update.update({'bonuses': 0})
                if not item.noncash == 0:
                    item_update.update({'noncash': 0})
            else:
                subtotal += item.price * item.quantity
                customer_discount += int(item.price * item.quantity *
                                         self.discount_percent / 100)
                if item.customer_discount != int(
                        item.price * self.discount_percent / 100):
                    item_update.update({
                        'customer_discount':
                        int(item.price * item.quantity *
                            self.discount_percent / 100)
                    })

            if item_update:
                await item.update(**item_update).apply()

        total = subtotal - customer_discount - promocode_discount - bonuses - noncash

        if self.subtotal != subtotal:
            self_update.update({'subtotal': subtotal})
        if self.customer_discount != customer_discount:
            self_update.update({'customer_discount': customer_discount})
        if self.promocode_discount != promocode_discount:
            self_update.update({'promocode_discount': promocode_discount})
        if self.bonuses != bonuses:
            self_update.update({'bonuses': bonuses})
        if self.noncash != noncash:
            self_update.update({'noncash': noncash})
        if self.total != total:
            self_update.update({'total': total})
        if self_update:
            await self.update(**self_update).apply()

    async def get_lines(self, include_deleted=False):
        from utils.db_api.models.orders_lines import OrderLine
        if include_deleted:
            items = await OrderLine.query.where(OrderLine.order_id == self.id
                                                ).gino.all()
        else:
            items = await OrderLine.query.where(
                and_(OrderLine.order_id == self.id,
                     OrderLine.deleted_at == None)).gino.all()

        return items

    async def set_satus(self, new_status_id: int):
        if new_status_id == 2:
            await self.update(status_id=new_status_id).apply()

    async def get_description(self, need_recalculate: bool = False):

        if need_recalculate:
            await self.recalculate()

        result = f"Заказ №{self.id}\n"
        result += f"-" * 50 + "\n\n"
        order_lines = await self.get_lines()

        for line_number, order_line in enumerate(order_lines, 1):
            result += f"{line_number}. " + await order_line.get_description(
            ) + "\n"

        result += f"-" * 50 + "\n"
        result += "\n"
        if self.subtotal:
            result += f"Сумма товаров: {self.subtotal}{currency_symbol}\n"
        if self.customer_discount:
            result += f"Скидка {self.discount_percent}%: {self.customer_discount}{currency_symbol}\n"
        if self.noncash:
            result += f"Оплачено: {self.noncash}{currency_symbol}\n"
        if self.total:
            result += f"К оплате: {self.total} \n"
        return result

    @classmethod
    async def add(cls, tg_user: types.User):
        try:
            obj = Order(customer_id=tg_user.id, status_id=1)
            await obj.create()
            return obj
        except UniqueViolationError:
            pass

    @classmethod
    async def get_or_add(cls, tg_user: types.User):
        obj = await cls.get(tg_user=tg_user, status_id=1)
        if not obj:
            obj = await cls.add(tg_user=tg_user)
        return obj

    @classmethod
    async def get(cls,
                  order_id: int = None,
                  tg_user: types.User = None,
                  status_id: int = 1):
        if order_id:
            obj = await cls.query.where(cls.id == order_id).gino.first()
        else:
            obj = await cls.query.where(
                and_(cls.customer_id == tg_user.id,
                     cls.status_id == status_id)).gino.first()

        return obj
Beispiel #11
0
class OrderLine(TimedBaseModel):
    __tablename__ = 'orders_lines'

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    order_id = db.Column(db.Integer, db.ForeignKey('orders.id'), nullable=False)
    product_id = db.Column(db.Integer, db.ForeignKey('products.id'), nullable=False)

    quantity = db.Column(db.Integer)
    price = db.Column(db.Integer)
    customer_discount = db.Column(db.Integer, default=0)
    promocode_id = db.Column(db.Integer, db.ForeignKey('promocodes.id'), nullable=True)
    promocode_discount = db.Column(db.Integer, default=0)
    bonuses = db.Column(db.Integer, default=0)
    noncash = db.Column(db.Integer, default=0)

    query: sql.Select

    @property
    async def product(self):
        item = await Product.get(self.product_id)
        return item

    async def get_description(self):
        product = await self.product
        result = f""
        if self.deleted_at is not None:
            result = f"{emoji_delete} строка удалена\n"
        result += f"{product.product_name}\n" \
                  f"<code>{self.quantity} шт. X {self.price}{currency_symbol} " \
                  f"= {self.price * self.quantity}{currency_symbol}\n</code>"
        return result

    @classmethod
    async def get(cls, order_line_id: int):
        obj = await cls.query.where(
            and_(
                cls.id == order_line_id
            )).order_by(cls.id).gino.first()
        return obj

    @classmethod
    async def paginator(cls, order: Order, line_number=1):
        lines = await cls.query.where(
            and_(
                cls.order_id == order.id
            )).order_by(cls.id).gino.all()

        lines_count = len(lines)
        if line_number > lines_count:
            current_line = lines_count
        elif line_number < 1:
            current_line = 1
        else:
            current_line = line_number

        order_line = lines[current_line - 1]

        result = {
            'order_line': order_line,
            'page': {
                'first': 1,
                'previous': 1 if current_line == 1 else current_line - 1,
                'current': current_line,
                'next': current_line + 1 if current_line < lines_count else lines_count,
                'last': lines_count,
            }
        }

        return result

    async def set_quantity(self, quantity: int = 1):
        try:
            data_update = {}
            if quantity > 0:
                data_update = {'quantity': quantity, 'deleted_at': None}
            else:
                data_update = {'quantity': 0, 'deleted_at': func.now()}

            if data_update:
                await self.update(**data_update).apply()

        except UniqueViolationError:
            pass

    @classmethod
    async def add(cls, order: Order, product: Product, price: int, quantity: int = 1):
        try:
            current_lines = await cls.query.where(
                and_(cls.order_id == order.id, cls.product_id == product.id, cls.deleted_at is None)
            ).gino.all()
            # Если нет строк и количество больше 0, тогда добавить строку
            if quantity > 0 and len(current_lines) == 0:
                obj = OrderLine(order_id=order.id, product_id=product.id, quantity=quantity, price=price)
                await obj.create()
            elif quantity > 0 and len(current_lines) == 1:
                line = current_lines[0]
                line_update = {'quantity': quantity, 'price': price}
                if line_update:
                    await line.update(**line_update).apply()
            elif quantity == 0 and len(current_lines) == 1:
                line = current_lines[0]
                line_update = {'quantity': quantity, 'price': price, 'deleted_at': func.now()}
                if line_update:
                    await line.update(**line_update).apply()

        except UniqueViolationError:
            pass