class Entity(BaseModel): __tablename__ = "entities" id = db.Column(db.Integer, primary_key=True, autoincrement=True) code = db.Column(db.String(50), unique=True) name = db.Column(db.String(50), unique=False, default='') query: sql.select @classmethod async def get(cls, code: str): item = await cls.query.where(cls.code == code.lower()).gino.first() return item @classmethod async def add(cls, code: str, name: str = ''): try: obj = cls(code=code, name=name) await obj.create() except UniqueViolationError: pass @classmethod async def get_all(cls): objs = await cls.query.gino.all() return objs
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
class Status(BaseModel): __tablename__ = 'statuses' id = db.Column(db.Integer, primary_key=True, autoincrement=True) status_name = db.Column(db.String(50), unique=True) comment = db.Column(db.String(255), default='') query: sql.Select
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()
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
class User(BaseModel): __tablename__ = 'users' query: sql.Select user_id = Column(db.BigInteger, primary_key=True) username = Column(db.String(20)) full_name = Column(db.String(40)) balance = Column(db.Numeric(precision=9, scale=2, decimal_return_scale=2), default=0) phone = Column(db.String(15), default=None) shipping_info = Column(db.String(100)) referral = Column(db.BigInteger)
class ProductsCategories(BaseModel): __tablename__ = 'products_categories' id = db.Column(db.Integer, primary_key=True, autoincrement=True) name = db.Column(db.String(100)) query: sql.Select
class Course(db.Model): __tablename__ = 'courses' query: sql.Select # Уникальный идентификатор товара id = Column(Integer, Sequence('plate_id_seq'), primary_key=True) # Название блюда (для отображения в колбек дате) name = Column(db.String(50)) # Тип меню (для отображения в кнопке) menu_type = Column(String(50)) # Тип блюда (для отображения в кнопке) course_type = Column(String(50)) price = Column(Integer) # Описание блюда description = Column(String(255)) # Название ресторана (для отображения в кнопке) rest = Column(String(50)) course_code = Column(String(50))
class Item(BaseModel): __tablename__ = "items" query: sql.Select id = Column(db.Integer, Sequence("item_id_seq"), primary_key=True) name = Column(db.String(20)) photo_id = Column(db.String(100)) small_photo = Column(db.String(50)) description = Column(db.String(250)) price: Decimal = Column( Numeric(precision=9, scale=2, decimal_return_scale=2)) def __repr__(self): return \ f"""
class User(db.Model): __tablename__ = 'users' query: sql.Select id = db.Column(db.Integer, Sequence('user_id_seq'), primary_key=True) user_name = db.Column(db.String(50)) user_tg_id = db.Column(db.Integer, unique=True, index=True) date_of_create = db.Column(DateTime, default=datetime.utcnow) def __repr__(self): return f'''
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'''
class Promocode(BaseModel): __tablename__ = "promocodes" id = db.Column(db.Integer, primary_key=True, autoincrement=True) code = db.Column(db.String(50), unique=True) day_expire = db.Column(db.Integer, default=0) start = db.Column(db.Date, default='2020-01-01') finish = db.Column(db.Date, default='2099-12-31') @classmethod async def get(cls, code: str): item = await cls.query.where(cls.code == code.upper()).gino.first() return item
class MenuOptions(db.Model): __tablename__ = 'menuoptions' query: sql.Select id = Column(db.Integer, Sequence("user_id_seq"), primary_key=True) category_code = Column(db.String(20)) category_name = Column(db.String(50)) subcategory_code = Column(db.String(20)) subcategory_name = Column(db.String(50)) name = Column(db.String(50)) photo = Column(db.String(250))
class Rest(db.Model): __tablename__ = 'restaurants' query: sql.Select # Уникальный идентификатор товара id = Column(Integer, Sequence('rest_id_seq'), primary_key=True) # Имя ресторана (для отображения в колбек дате) rest_name = Column(db.String(50)) # Уникальный код ресторана (для отображения в колбек дате) rest_code = Column(String(20)) # Логин владельца (для отображения в кнопке) login = Column(String(50)) # Пароль владельца (для отображения в колбек дате) password = Column(String(50)) # Номер телефона ресторана (для отображения в кнопке) phone = Column(String(50)) # Описание ресторана description = Column(String(255))
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