sfx-tg-bot/handlers/handlers.py

375 строки
12 KiB
Python
Исходник Обычный вид История

2024-07-26 03:30:01 +03:00
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',
)