sfx-tg-bot/handlers/handlers.py

375 строки
12 KiB
Python

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',
)