import api import database import models from errors import Error import logging import messages from models import Message, FSMContext import psycopg import re async def start(message: Message, state: FSMContext): if message.text == 'Записаться': return await messages.select_category(message, state) if message.text == 'Мои обращения': return await messages.select_order(message, state) await message.answer( text=Error(0x00000001), parse_mode='HTML', ) async def select_category(message: Message, state: FSMContext): if message.text == 'Назад': return await messages.start(message, state) try: category = tuple( category for category in await database.read_categories() if category.name == message.text )[0] await state.update_data({ 'category': category, }) await messages.select_subcategory(message, state) except IndexError: await message.answer( text=Error(0x00000001), parse_mode='HTML', ) async def select_subcategory(message: Message, state: FSMContext): if message.text == 'Назад': return await messages.select_category(message, state) try: data = await state.get_data() subcategory = tuple( subcategory for subcategory in await database.read_subcategories(data['category']) if subcategory.name == message.text )[0] try: free_to_order = await database.read_free_to_order(subcategory) await state.update_data({ 'subcategory': subcategory, 'free_to_order': free_to_order, }) await messages.select_date(message, state) except psycopg.errors.RaiseException as error: if error.diag.message_primary == '0x00000005': logging.error('\n\tКатегория: %s\n\tПодкатегория: %s\n\n\tСредняя длительность выполнения заказа указанной подкатегории (таблица statistics) дольше, чем все временные промежутки (таблица time_ranges).' % ( subcategory.category.name, subcategory.name, )) return await message.answer( text=Error(0x00000005), parse_mode='HTML', ) raise except IndexError: await message.answer( text=Error(0x00000001), parse_mode='HTML', ) async def select_date(message: Message, state: FSMContext): if message.text == 'Назад': return await messages.select_subcategory(message, state) try: data = await state.get_data() free_to_order = tuple( item for item in data['free_to_order'] if item.date.strftime('%d.%m') == message.text )[0] await state.update_data({ 'date': free_to_order.date, }) await messages.select_time_range(message, state) except IndexError: await message.answer( text=Error(0x00000001), parse_mode='HTML', ) async def select_time_range(message: Message, state: FSMContext): if message.text == 'Назад': return await messages.select_date(message, state) try: data = await state.get_data() free_to_order = tuple( item for item in data['free_to_order'] if '%s - %s' % ( item.time_range.start_time.strftime('%H:%M'), item.time_range.end_time.strftime('%H:%M'), ) == message.text )[0] await state.update_data({ 'time_range': free_to_order.time_range, }) await messages.input_email_address(message, state) except IndexError: await message.answer( text=Error(0x00000001), parse_mode='HTML', ) async def input_email_address(message: Message, state: FSMContext): if message.text == 'Назад': return await messages.select_time_range(message, state) match = re.match(models.email_address, message.text.strip()) if match is None: return await message.answer( text=Error(0x00000003), parse_mode='HTML', ) await state.update_data({ 'email_address': match.string, }) await messages.input_phone_number(message, state) async def input_phone_number(message: Message, state: FSMContext): if message.text == 'Назад': return await messages.input_email_address(message, state) phone_number = re.sub(models.phone_number, '', message.text) if len(phone_number) not in range(8, 16): return await message.answer( text=Error(0x00000004), parse_mode='HTML', ) await state.update_data({ 'phone_number': '+%s' % phone_number, }) await messages.input_comment(message, state) async def input_comment(message: Message, state: FSMContext): if message.text == 'Назад': return await messages.input_phone_number(message, state) comment = message.text if len(comment) > models.max_comment_length: return await message.answer( text=Error(0x00000002), parse_mode='HTML', ) await state.update_data({ 'comment': comment, }) await messages.confirm_order(message, state) async def confirm_order(message: Message, state: FSMContext): if message.text == 'Назад': return await messages.input_comment(message, state) if message.text == 'Подтвердить': data = await state.get_data() # executor = sorted( # tuple( # item # for item in data['free_to_order'] # if item.date == data['date'] and item.time_range == data['time_range'] # ), # key=lambda x: x.busy_interval, # )[0].executor # order_id = await database.create_order( # subcategory=data['subcategory'], # date=data['date'], # time_range=data['time_range'], # executor=executor, # telegram_id=message.from_user.id, # email_address=data['email_address'], # phone_number=data['phone_number'], # comment=data['comment'], # ) # orders = await database.read_orders(message.from_user.id) issue = await api.create_issue( subcategory=data['subcategory'], _date=data['date'], time_range=data['time_range'], email_address=data['email_address'], phone_number=data['phone_number'], comment=data['comment'], firstname=message.from_user.first_name, ) await state.update_data({ # 'executor': executor, 'issue_key': issue.key, }) await database.create_issue( issue=models.Issue( id=issue.id, key=issue.key, status='new', telegram_id=message.from_user.id, ), ) return await messages.success_sign_up(message, state) await message.answer( text=Error(0x00000001), parse_mode='HTML', ) async def success_sign_up(message: Message, state: FSMContext): if message.text == 'Главное меню': return await messages.start(message, state) await message.answer( text=Error(0x00000001), parse_mode='HTML', ) async def select_order(message: Message, state: FSMContext): if message.text == 'Назад': return await messages.start(message, state) try: issue = tuple( issue for issue in await database.read_issues(message.from_user.id) if issue.key == message.text )[0] await state.update_data({ 'issue': issue, }) await messages.select_operation(message, state) except IndexError: await message.answer( text=Error(0x00000001), parse_mode='HTML', ) async def no_orders(message: Message, state: FSMContext): if message.text == 'Главное меню': return await messages.start(message, state) await message.answer( text=Error(0x00000001), parse_mode='HTML', ) async def select_operation(message: Message, state: FSMContext): if message.text == 'Назад': return await messages.select_order(message, state) if message.text == 'Перенести': data = await state.get_data() free_to_order = await database.read_free_to_order(data['order'].subcategory) await state.update_data({ 'free_to_order': free_to_order, }) return await messages.reschedule_order_select_date(message, state) if message.text == 'Отменить': return await messages.cancel_order(message, state) await message.answer( text=Error(0x00000001), parse_mode='HTML', ) async def reschedule_order_select_date(message: Message, state: FSMContext): if message.text == 'Назад': return await messages.select_operation(message, state) try: data = await state.get_data() free_to_order = tuple( item for item in data['free_to_order'] if item.date.strftime('%d.%m') == message.text )[0] await state.update_data({ 'date': free_to_order.date, }) await messages.reschedule_order_select_time_range(message, state) except IndexError: await message.answer( text=Error(0x00000001), parse_mode='HTML', ) async def reschedule_order_select_time_range(message: Message, state: FSMContext): if message.text == 'Назад': return await messages.reschedule_order_select_date(message, state) try: data = await state.get_data() free_to_order = tuple( item for item in data['free_to_order'] if '%s - %s' % ( item.time_range.start_time.strftime('%H:%M'), item.time_range.end_time.strftime('%H:%M'), ) == message.text )[0] executor = sorted( tuple( item for item in data['free_to_order'] if item.date == data['date'] and item.time_range == free_to_order.time_range ), key=lambda x: x.busy_interval, )[0].executor await state.update_data({ 'executor': executor, }) await database.update_order( order_id=data['order'].id, date=data['date'], time_range=free_to_order.time_range, executor=executor, ) await messages.success_reschedule_order(message, state) except IndexError: await message.answer( text=Error(0x00000001), parse_mode='HTML', ) async def success_reschedule_order(message: Message, state: FSMContext): if message.text == 'Мои обращения': await state.reset_data() return await messages.select_order(message, state) await message.answer( text=Error(0x00000001), parse_mode='HTML', ) async def cancel_order(message: Message, state: FSMContext): if message.text == 'Назад': return await messages.select_operation(message, state) if message.text == 'Отменить заказ': data = await state.get_data() issue = await api.read_issue( issue_id=data['issue'].id, ) issue.delete() await database.delete_issue( issue=issue, ) # await database.delete_order( # order_id=data['issue'].id, # ) return await messages.success_cancel_order(message, state) await message.answer( text=Error(0x00000001), parse_mode='HTML', ) async def success_cancel_order(message: Message, state: FSMContext): if message.text == 'Мои обращения': await state.reset_data() return await messages.select_order(message, state) await message.answer( text=Error(0x00000001), parse_mode='HTML', )