def perform_invoice(self, db: DBManager, order_id): """ perform invoice PDF file in directory invoices :param db: :param order_id: :return: """ if config.is_company_info(): info = config.company_info() invoice = ReportInvoice() invoice.company_info(info) order = db.get_order_info(order_id=order_id) client = db.get_client(order.client_id) invoice.set_order(date=order.order_date, number=order_id, payer=client.title, address=client.address, delivery=order.delivery_cost) order_items = db.get_order_items(order_id) for item in order_items: product = db.select_single_product(item.product_id) invoice.add_item(name=product.name, code=product.title, unit='шт.', quantity=item.quantity, price=product.price) invoice.make() _send_invoice_mail(client, order_id)
def save(self, db: DBManager): if self._id: order = db.get_order(self._id) order.is_current = self.is_current order.product_id = self.product_id order.quantity = self.quantity db.save_element(order) else: db.save_element(self.get_order())
def change_status(db: DBManager, order_id, order_status): """ change status of order :param db: :param order_id: :param order_status: :return: """ order: OrderInfo = db.get_order_info(order_id=order_id) order.status = order_status db.save_element(order)
def dialog_store_save(self, db: DBManager): """ save info about store from dialog to database :return: """ store = Store() store.title = self._dialog.store['title'] store.address = self._dialog.store['address'] store.longitude = self._dialog.store['longitude'] store.latitude = self._dialog.store['latitude'] store.price_km = self._dialog.store['price'] db.save_element(store)
def save(self, db: DBManager): if self._id: order = db.get_order_info(self._id) order.is_current = self._current order.client_id = self._client order.delivery_cost = self._delivery_cost order.order_date = self._date order.status = self._status order.store_id = self._store db.save_element(order) else: self._date = datetime.now() order = self._get_order_info() self._id = db.save_element(order) return order
def __init__(self, bot): # получаем нашего бота self.bot = bot # инициализируем разметку кнопок в меню и экрана self.keybords = Keyboards() # инициализация менеджера для работы с БД self.BD = DBManager()
def get_orders(self, db: DBManager): """ get a list of orders with status like self._order_status from order_info table :param db: :return orders: list of order objects """ orders = db.get_orders_status(status=self._order_status) return orders
def load(self, db: DBManager, order_id): self._id = order_id order_info = db.get_order_info(order_id) self._client = order_info.client_id self._current = order_info.is_current self._date = order_info.order_date self._delivery_cost = order_info.delivery_cost self._status = order_info.status self._store = order_info.store_id
def get_orders(self, db: DBManager): """ get list of orders from order_info table or get only one current order """ order = self._load_current_order(db=db) if order: return [order] else: orders = db.get_orders_info(self._id) return orders
def _load(self, db: DBManager, order_spec): products = db.get_order_items(order_spec.id) number = 0 for order in products: number += 1 order_item = OrderItem(order_spec=order_spec, number=number, is_current=order.is_current, product_id=order.product_id, quantity=order.quantity, item_id=order.id) order_item.order_id = order.order_id self._orders[order_item.product_id] = order_item
def _get_store_near(self, db: DBManager): client = db.get_client(self._client) stores = db.get_stores() client_distance = 0.0 store_distance = 0.0 store_id = 0 price_km = 0.0 client_location = (client.latitude, client.longitude) for store in stores: store_location = (store.latitude, store.longitude) if client_distance == 0.0: client_distance = distance(client_location, store_location).kilometers store_id = store.id price_km = store.price_km continue store_distance = distance(client_location, store_location).kilometers if store_distance < client_distance: client_distance = store_distance store_id = store.id price_km = store.price_km return client_distance, store_id, price_km
def dec_item(self, db: DBManager, product_id, quantity=1): """ decrease number of order item :param db: link to DBManager :param product_id: :param quantity: :return: """ if self.order.id > 0: # return quantity of product to store if self.order_items._dec(product_id=product_id, quantity=quantity): if db.increase_product(product_id=product_id, quantity=quantity): self.order_items._save(db)
def add_item(self, db: DBManager, product_id, quantity=1): """ add item to order, if enough product quantity :param db: link to DBManager :param product_id: :param quantity: :return True: if enough products, False: otherwise """ if self.order.id == 0: self.order.save(db) # check if product quantity enough if db.decrease_product(product_id=product_id, quantity=quantity): self.order_items._add(order_spec=self.order, product_id=product_id, quantity=quantity) self.order_items._save(db) return True else: return False
def _del(self, db: DBManager, order_spec, product_id): """ delete order item position :param db: :param product_id: :return: """ if product_id in self._orders: order_item = self._orders[product_id] numbers = self.number_positions if db.increase_product(product_id=product_id, quantity=order_item.quantity): if numbers > 1: if 1 < order_item.number < numbers or order_item.number == numbers: self.current_prev(db) elif order_item.number == 1: self.current_next(db) order_item.delete(db) self._orders = OrderedDict() self._load(db=db, order_spec=order_spec)
class Keyboards: """ Класс Keyboards предназначен для создания и разметки клавиатуры бота """ # инициализация разметки def __init__(self): self.markup = None # инициализация менеджера для работы с БД self.BD = DBManager() def set_btn(self, name, step=0, quantity=0): """ Создает и возвращает кнопку по входным параметрам """ if name == "AMOUNT_ORDERS": config.KEYBOARD["AMOUNT_ORDERS"] = "{} {} {}".format( step + 1, ' из ', str(self.BD.count_rows_order())) if name == "AMOUNT_PRODUCT": config.KEYBOARD["AMOUNT_PRODUCT"] = "{}".format(quantity) if name == "APPLY": # создает кнопку оформить с данными о стоимости товара # округленного до 2 - го знака после запятой config.KEYBOARD["APPLY"] = "{}({}) руб".format( '✅ Оформить', round(utility.get_total_cost(self.BD), 2)) return KeyboardButton(config.KEYBOARD[name]) @staticmethod def set_inline_btn(name): """ Создает и возвращает инлайн кнопку по входным параметрам """ return InlineKeyboardButton(str(name), callback_data=str(name.id)) @staticmethod def remove_menu(): """ Удаляет данны кнопки и возвращает ее """ return ReplyKeyboardRemove() def info_menu(self): """ Создает разметку кнопок в меню info """ self.markup = ReplyKeyboardMarkup(True, True) itm_btn_1 = self.set_btn('<<') # расположение кнопок в меню self.markup.row(itm_btn_1) return self.markup def settings_menu(self): """ Создает разметку кнопок в меню settings """ self.markup = ReplyKeyboardMarkup(True, True) itm_btn_1 = self.set_btn('<<') # расположение кнопок в меню self.markup.row(itm_btn_1) return self.markup def start_menu(self): """ Создает разметку кнопок в основном меню и возвращает разметку """ self.markup = ReplyKeyboardMarkup(True, True) itm_btn_1 = self.set_btn('CHOOSE_GOODS') itm_btn_2 = self.set_btn('INFO') itm_btn_3 = self.set_btn('SETTINGS') # рассположение кнопок в меню self.markup.row(itm_btn_1) self.markup.row(itm_btn_2, itm_btn_3) return self.markup def category_menu(self): """ Создает разметку кнопок в меню категорий товара и возвращает разметку """ self.markup = ReplyKeyboardMarkup(True, True, row_width=1) self.markup.add(self.set_btn('SEMIPRODUCT')) self.markup.add(self.set_btn('GROCERY')) self.markup.add(self.set_btn('ICE_CREAM')) self.markup.row(self.set_btn('<<'), self.set_btn('ORDER')) return self.markup def set_select_category(self, category): """ Создает разметку инлайн кнопок в выбранной категории товара и возвращает разметку """ self.markup = InlineKeyboardMarkup(row_width=1) # загружаем в название инлайн кнопок данные с БД # в соответствие с категорией товара for item in self.BD.select_all_products_category(category): self.markup.add(self.set_inline_btn(item)) return self.markup def orders_menu(self, step, quantity): """ Создает разметку кнопок в заказе товара и возвращает разметку """ self.markup = ReplyKeyboardMarkup(True, True) itm_btn_1 = self.set_btn('X', step, quantity) itm_btn_2 = self.set_btn('DOWN', step, quantity) itm_btn_3 = self.set_btn('AMOUNT_PRODUCT', step, quantity) itm_btn_4 = self.set_btn('UP', step, quantity) itm_btn_5 = self.set_btn('BACK_STEP', step, quantity) itm_btn_6 = self.set_btn('AMOUNT_ORDERS', step, quantity) itm_btn_7 = self.set_btn('NEXT_STEP', step, quantity) itm_btn_8 = self.set_btn('APPLY', step, quantity) itm_btn_9 = self.set_btn('<<', step, quantity) # рассположение кнопок в меню self.markup.row(itm_btn_1, itm_btn_2, itm_btn_3, itm_btn_4) self.markup.row(itm_btn_5, itm_btn_6, itm_btn_7) self.markup.row(itm_btn_9, itm_btn_8) return self.markup
class Keyboards: """ Класс Keyboards предназначен для создания и разметки клавиатуры бота """ # инициализация разметки def __init__(self): self.markup = None # инициализация менеджера для работы с БД self.BD = DBManager() def set_btn(self, name, step='', quantity=0): """ Создает и возвращает кнопку по входным параметрам """ if name == "AMOUNT_ORDERS": config.KEYBOARD["AMOUNT_ORDERS"] = step if name == "AMOUNT_PRODUCT": config.KEYBOARD["AMOUNT_PRODUCT"] = "{}".format(quantity) if name == "APPLY": # создает кнопку оформить с данными о стоимости товара округленного до 2 - го знака после запятой config.KEYBOARD["APPLY"] = "{}({}) руб".format('✅ Оформить', step) return KeyboardButton(config.KEYBOARD[name]) def set_inline_btn(self, name, data=''): """ Создает и возвращает инлайн кнопку по входным параметрам """ if len(data) == 0: data = str(name.id) return InlineKeyboardButton(str(name), callback_data=data) def remove_menu(self): """ Удаляет данны кнопки и возвращает ее """ return ReplyKeyboardRemove() def info_menu(self): """ Создает разметку кнопок в меню info """ self.markup = ReplyKeyboardMarkup(True, True) itm_btn_1 = self.set_btn('<<') # рассположение кнопок в меню self.markup.row(itm_btn_1) return self.markup def settings_menu(self): """ Создает разметку кнопок в меню settings """ self.markup = ReplyKeyboardMarkup(True, True) itm_btn_1 = self.set_btn('<<') # рассположение кнопок в меню self.markup.row(itm_btn_1) return self.markup def start_menu(self): """ Создает разметку кнопок в основном меню и возвращает разметку """ self.markup = ReplyKeyboardMarkup(True, True) itm_btn_1 = self.set_btn('CHOOSE_ORDER') itm_btn_2 = self.set_btn('CHOOSE_GOODS') itm_btn_3 = self.set_btn('INFO') itm_btn_4 = self.set_btn('SETTINGS') # рассположение кнопок в меню self.markup.row(itm_btn_1, itm_btn_2) self.markup.row(itm_btn_3, itm_btn_4) return self.markup def current_order_menu(self): """ making markup for work with order :return: """ self.markup = ReplyKeyboardMarkup(True, True) itm_btn_1 = self.set_btn('CHOOSE_ORDER') itm_btn_2 = self.set_btn('CHOOSE_GOODS') itm_btn_3 = self.set_btn('<<') itm_btn_4 = self.set_btn('ORDER') # рассположение кнопок в меню self.markup.row(itm_btn_1, itm_btn_2) self.markup.row(itm_btn_3, itm_btn_4) return self.markup def category_menu(self): """ Создает разметку кнопок в меню категорий товара и возвращает разметку """ self.markup = ReplyKeyboardMarkup(True, True, row_width=1) self.markup.add(self.set_btn('SEMIPRODUCT')) self.markup.add(self.set_btn('GROCERY')) self.markup.add(self.set_btn('ICE_CREAM')) self.markup.row(self.set_btn('<<'), self.set_btn('ORDER')) return self.markup def select_role_menu(self): """ markup for role selection """ self.markup = ReplyKeyboardMarkup(True, True, row_width=1) itm_btn_1 = self.set_btn('TRADER') itm_btn_2 = self.set_btn('KEEPER') itm_btn_3 = self.set_btn('ADMIN') self.markup.row(itm_btn_1, itm_btn_2, itm_btn_3) return self.markup def set_select_category(self, trader, category): """ Создает разметку инлайн кнопок в выбранной категории товара и возвращает разметку """ self.markup = InlineKeyboardMarkup(row_width=1) # загружаем в название инлайн кнопок данные с БД в соответствие с категорией товара order_current = self.BD.get_order_current(trader_id=trader.id) if order_current is None: order_current = trader.order.save(self.BD) for itm in self.BD.select_all_products_category(category): # dump a data to json string # keys & values are: 'm' - menu: 'p' - products (add one product) # 't' - trader id # 'o' - current order id # 'p' - product id data = json.dumps( { 'm': 'p', 't': trader.id, 'o': order_current.id, 'p': itm.id }, separators=(',', ':')) self.markup.add(self.set_inline_btn(str(itm), data)) return self.markup def orders_info_menu(self, trader_user: TraderUser): """ create inline-menu of trader's orders :param trader_user: :return: markup """ orders = trader_user.get_orders(self.BD) self.markup = InlineKeyboardMarkup(row_width=1) if len(orders): for order in orders: # dump a data to json string # keys & values are: 'm' - menu: 'o' - orders (choose one order to work with) # 't' - trader id # 'o' - current order id data = json.dumps( { 'm': 'o', 't': trader_user.id, 'o': order.id }, separators=(',', ':')) self.markup.add(self.set_inline_btn(str(order), data)) return self.markup def set_select_client(self, trader: TraderUser): """ set menu of list of clients :param trader: :return markup: inline buttons """ clients = self.BD.get_clients() if len(clients): self.markup = InlineKeyboardMarkup(row_width=1) for client in clients: # dump a data to json string # keys & values are: 'm' - menu: 'c' - clients (choose one client for order) # 't' - trader id # 'o' - order id # 'c' - client id data = json.dumps({ 'm': 'c', 't': trader.id, 'o': trader.order.id, 'c': client.id }) self.markup.add(self.set_inline_btn(str(client), data)) return self.markup def orders_menu(self, step): """ Создает разметку кнопок в заказе товара и возвращает разметку :param step: json with parameters: number, quantity, positions, total_price :return: markup """ parameters = json.loads(step) self.markup = ReplyKeyboardMarkup(True, True) itm_btn_1 = self.set_btn('X') itm_btn_2 = self.set_btn('DOWN') itm_btn_3 = self.set_btn('AMOUNT_PRODUCT', quantity=parameters['quantity']) itm_btn_4 = self.set_btn('UP') itm_btn_5 = self.set_btn('BACK_STEP') itm_btn_6 = self.set_btn('AMOUNT_ORDERS', step='{} из {}'.format( parameters['number'], parameters['positions'])) itm_btn_7 = self.set_btn('NEXT_STEP') itm_btn_8 = self.set_btn('APPLY', step=parameters['total_price']) itm_btn_9 = self.set_btn('<<') # рассположение кнопок в меню self.markup.row(itm_btn_1, itm_btn_2, itm_btn_3, itm_btn_4) self.markup.row(itm_btn_5, itm_btn_6, itm_btn_7) self.markup.row(itm_btn_9, itm_btn_8) return self.markup
def __init__(self): self.markup = None # инициализация менеджера для работы с БД self.BD = DBManager()
def delete(self, db: DBManager): if self._id: order = db.get_order(self._id) db.delete_element(order)
def _load_current_order(self, db: DBManager): return db.get_order_current(trader_id=self._id)
def _load(self, db: DBManager): user = db.get_user_id(self._id) if user: self._chat_id = user.chat_id
def total_price(self, db: DBManager): price = 0 for order_item in self._orders.values(): product = db.select_single_product(rownum=order_item.product_id) price += product.price * order_item.quantity return round(price, 2)