458 lines
15 KiB
Python
458 lines
15 KiB
Python
|
import datetime
|
|||
|
import logging
|
|||
|
|
|||
|
from aiogram.fsm.state import StatesGroup, State
|
|||
|
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup, FSInputFile
|
|||
|
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
|||
|
|
|||
|
from config import FILES_PATH, ROLE_MODERATOR_ID, ROLE_CURATOR_ID
|
|||
|
from core import bot
|
|||
|
from utils.bitrix import notify
|
|||
|
from utils.db import get_data, query
|
|||
|
|
|||
|
|
|||
|
class ModerationState(StatesGroup):
|
|||
|
confirm = State()
|
|||
|
confirm_confirm = State()
|
|||
|
revision = State()
|
|||
|
grade = State()
|
|||
|
reject = State()
|
|||
|
check_revision_comment = State()
|
|||
|
check_reject_comment = State()
|
|||
|
date = State()
|
|||
|
|
|||
|
|
|||
|
new_idea_text = """
|
|||
|
{name}, пожалуйста, ознакомьтесь с новой НеоИдеей.
|
|||
|
"""
|
|||
|
|
|||
|
new_idea_data_text = """
|
|||
|
<b>Автор:</b> {author_name}
|
|||
|
<b>Дата:</b> {creation_date}
|
|||
|
<b>Подразделение:</b> {department}
|
|||
|
<b>Категория:</b> {category}
|
|||
|
<b>Город:</b> {city}
|
|||
|
<b>Название:</b> «{idea_name}»
|
|||
|
<b>Содержание:</b> {idea_content}
|
|||
|
"""
|
|||
|
|
|||
|
choose_action_text = """
|
|||
|
Пожалуйста, выберите одно из следующих действий:
|
|||
|
"""
|
|||
|
|
|||
|
confirm_action_text = """
|
|||
|
<b>Вы согласовываете НеоИдею:</b>
|
|||
|
«{idea_name}».
|
|||
|
|
|||
|
<b>Автор:</b> {author_name}
|
|||
|
"""
|
|||
|
|
|||
|
choose_responsible_text = """
|
|||
|
Пожалуйста, выберите <b>Ответственного за категорию</b> для передачи НеоИдеи в работу.
|
|||
|
"""
|
|||
|
|
|||
|
send_date_text = """
|
|||
|
В календаре укажите крайние сроки выполнения:
|
|||
|
"""
|
|||
|
|
|||
|
confirm_responsible_date_text = """
|
|||
|
Вы передаёте НеоИдею в работу.
|
|||
|
<b>Название:</b> «{idea_name}».
|
|||
|
|
|||
|
<b>Автор:</b> {author_name}
|
|||
|
<b>Ответственный за категорию:</b> {responsible_name}
|
|||
|
<b>Крайние сроки выполнения:</b> {date}
|
|||
|
"""
|
|||
|
|
|||
|
confirm_action_send_text = """
|
|||
|
Спасибо! Вы передали НеоИдею в работу.
|
|||
|
"""
|
|||
|
|
|||
|
revision_action_text = """
|
|||
|
<b>Вы возвращаете на доработку НеоИдею:</b>
|
|||
|
«{idea_name}».
|
|||
|
<b>Автор:</b> {author_name}
|
|||
|
|
|||
|
Оставьте комментарий для того, чтобы отправить НеоИдею на доработку.
|
|||
|
"""
|
|||
|
|
|||
|
send_revision_comment_text = """
|
|||
|
Оставьте комментарий для того, чтобы отправить НеоИдею на доработку
|
|||
|
"""
|
|||
|
|
|||
|
send_comment_text = """
|
|||
|
Пожалуйста, оставьте свой комментарий:
|
|||
|
"""
|
|||
|
|
|||
|
check_comment = """
|
|||
|
Проверьте правильность введенных данных:
|
|||
|
|
|||
|
{comment}
|
|||
|
"""
|
|||
|
|
|||
|
revision_action_send_text = """
|
|||
|
Вы отправили НеоИдею на доработку.
|
|||
|
"""
|
|||
|
|
|||
|
grade_action_text = """
|
|||
|
<b>Вы направляете НеоИдею на оценку:</b>
|
|||
|
«{idea_name}».
|
|||
|
<b>Автор:</b> {author_name}
|
|||
|
|
|||
|
НеоИдея будет передана Куратору.
|
|||
|
"""
|
|||
|
|
|||
|
grade_action_send_text = """
|
|||
|
Спасибо! НеоИдея передана Куратору.
|
|||
|
"""
|
|||
|
|
|||
|
reject_action_text = """
|
|||
|
<b>Вы отклоняете НеоИдею:</b>
|
|||
|
«{idea_name}».
|
|||
|
<b>Автор:</b> {author_name}
|
|||
|
|
|||
|
Пожалуйста, оставьте свой комментарий.
|
|||
|
"""
|
|||
|
|
|||
|
reject_action_send_text = """
|
|||
|
Спасибо! НеоИдея отклонена.
|
|||
|
"""
|
|||
|
|
|||
|
you_rejected = """
|
|||
|
Здравствуйте, {name}.
|
|||
|
|
|||
|
Ваша НеоИдея "{idea_name}" была отклонена с комментарием:
|
|||
|
"{comment}"
|
|||
|
"""
|
|||
|
|
|||
|
you_revision = """
|
|||
|
Ваша НеоИдея возвращена на доработку, пожалуйста проработайте комментарии от генерального директора и отправьте заявку заново.
|
|||
|
|
|||
|
НеоИдея: "{idea_name}"
|
|||
|
Комментарий: "{comment}"
|
|||
|
"""
|
|||
|
|
|||
|
accept_notify_author_text = """
|
|||
|
Поздравляем! Ваша НеоИдея передана к внедрению
|
|||
|
"""
|
|||
|
|
|||
|
accept_notify_curator_text = """
|
|||
|
Быстрая НеоИдея автора {author_name} передана к внедрению {responsible_name}
|
|||
|
"""
|
|||
|
|
|||
|
grade_curator_text = """
|
|||
|
Вам на оценку передана НеоИдея "{idea_name}".
|
|||
|
"""
|
|||
|
|
|||
|
confirm_notify_curator_text = """
|
|||
|
Быстрая НеоИдея автора {author_name} передана к ответственному за категорию {responsible_name}
|
|||
|
"""
|
|||
|
|
|||
|
confirm_notify_author_text = """
|
|||
|
Ваша НеоИдея передана ответственному за категорию
|
|||
|
"""
|
|||
|
|
|||
|
|
|||
|
def confirm_action_ikb() -> InlineKeyboardMarkup:
|
|||
|
"""
|
|||
|
-Да, продолжить ✅
|
|||
|
-Нет, вернуться назад ❌
|
|||
|
:return: объект клавиатуры для параметра reply_markup
|
|||
|
"""
|
|||
|
builder = InlineKeyboardBuilder()
|
|||
|
builder.add(
|
|||
|
InlineKeyboardButton(
|
|||
|
text='Да, продолжить ✅',
|
|||
|
callback_data='confirm_action_confirm'
|
|||
|
),
|
|||
|
InlineKeyboardButton(
|
|||
|
text='Нет, вернуться назад ❌',
|
|||
|
callback_data='confirm_action_reject'
|
|||
|
)
|
|||
|
)
|
|||
|
builder.adjust(1)
|
|||
|
return builder.as_markup()
|
|||
|
|
|||
|
|
|||
|
def choose_action_ikb(idea_id: str | int, msg_id: str | int) -> InlineKeyboardMarkup:
|
|||
|
"""
|
|||
|
-Согласовать и передать в работу
|
|||
|
-Вернуть Автору на доработку
|
|||
|
-Направить на оценку
|
|||
|
-Отклонить
|
|||
|
:param idea_id: ID идеи
|
|||
|
:param msg_id: ID сообщения с клавиатурой
|
|||
|
:return: объект клавиатуры для параметра reply_markup
|
|||
|
"""
|
|||
|
builder = InlineKeyboardBuilder()
|
|||
|
builder.add(
|
|||
|
InlineKeyboardButton(
|
|||
|
text='Согласовать и передать в работу',
|
|||
|
callback_data=f'moderation_confirm_{idea_id}_{msg_id}'
|
|||
|
),
|
|||
|
InlineKeyboardButton(
|
|||
|
text='Вернуть Автору на доработку',
|
|||
|
callback_data=f'moderation_revision_{idea_id}_{msg_id}'
|
|||
|
),
|
|||
|
InlineKeyboardButton(
|
|||
|
text='Направить на оценку',
|
|||
|
callback_data=f'moderation_grade_{idea_id}_{msg_id}'
|
|||
|
),
|
|||
|
InlineKeyboardButton(
|
|||
|
text='Отклонить',
|
|||
|
callback_data=f'moderation_reject_{idea_id}_{msg_id}'
|
|||
|
)
|
|||
|
)
|
|||
|
builder.adjust(1)
|
|||
|
return builder.as_markup()
|
|||
|
|
|||
|
|
|||
|
async def choose_responsible_ikb(category_id: int) -> InlineKeyboardMarkup:
|
|||
|
"""
|
|||
|
-Ответственный 1
|
|||
|
-Ответственный 2
|
|||
|
:param category_id: ID категории идеи
|
|||
|
:return: объект клавиатуры для параметра reply_markup
|
|||
|
"""
|
|||
|
builder = InlineKeyboardBuilder()
|
|||
|
responsible_list = await get_data(
|
|||
|
table_name='user_to_categories',
|
|||
|
query_filter={'category_id': category_id}
|
|||
|
)
|
|||
|
for responsible in responsible_list:
|
|||
|
responsible_data = await get_data(
|
|||
|
table_name='users',
|
|||
|
query_filter={'id': responsible['user_id']}
|
|||
|
)
|
|||
|
builder.add(
|
|||
|
InlineKeyboardButton(
|
|||
|
text=responsible_data[0]['full_name'],
|
|||
|
callback_data=f'choose_responsible_{responsible_data[0]["id"]}',
|
|||
|
)
|
|||
|
)
|
|||
|
builder.adjust(1)
|
|||
|
return builder.as_markup()
|
|||
|
|
|||
|
|
|||
|
async def send_new_idea_on_moderation(
|
|||
|
idea_id: int, user_name: str, department: str, idea_title: str,
|
|||
|
idea_content: str, relation_id: int, city_id: int, category_id: int, creation_date: datetime.datetime):
|
|||
|
"""
|
|||
|
Присылает новую идею модераторам из списка
|
|||
|
:param idea_id: Данные идеи
|
|||
|
:param user_name: Имя пользователя
|
|||
|
:param department: Отдел пользователя
|
|||
|
:param idea_title: Название идеи
|
|||
|
:param idea_content: Описание идеи
|
|||
|
:param relation_id: id отношения к идее
|
|||
|
:param city_id: id города, где работает пользователь
|
|||
|
:param category_id: id категории
|
|||
|
:param creation_date: Дата создания идеи
|
|||
|
:return:
|
|||
|
"""
|
|||
|
moderators = await get_data(
|
|||
|
table_name='user_to_roles',
|
|||
|
query_filter={'role_id': ROLE_MODERATOR_ID}
|
|||
|
)
|
|||
|
city = await get_data(
|
|||
|
table_name='cities',
|
|||
|
query_filter={'id': city_id}
|
|||
|
)
|
|||
|
files = await get_data(
|
|||
|
table_name='idea_to_files',
|
|||
|
query_filter={'idea_id': idea_id}
|
|||
|
)
|
|||
|
category = await get_data(
|
|||
|
table_name='categories',
|
|||
|
query_filter={'id': category_id}
|
|||
|
)
|
|||
|
notify_text = new_idea_data_text.format(
|
|||
|
author_name=user_name,
|
|||
|
creation_date=creation_date,
|
|||
|
department=department,
|
|||
|
idea_name=idea_title,
|
|||
|
idea_content=idea_content,
|
|||
|
city=city[0]['name'],
|
|||
|
category=category[0]['name']
|
|||
|
)
|
|||
|
|
|||
|
for moderator_id in moderators:
|
|||
|
try:
|
|||
|
moderator = await get_data(
|
|||
|
table_name='users',
|
|||
|
query_filter={'id': moderator_id['user_id']}
|
|||
|
)
|
|||
|
formatted_new_idea_text = new_idea_text.format(
|
|||
|
name=moderator[0]['full_name'],
|
|||
|
)
|
|||
|
await bot.send_message(
|
|||
|
chat_id=moderator[0]['telegram_id'],
|
|||
|
text=formatted_new_idea_text
|
|||
|
)
|
|||
|
await bot.send_message(
|
|||
|
chat_id=moderator[0]['telegram_id'],
|
|||
|
text=notify_text
|
|||
|
)
|
|||
|
for file in files:
|
|||
|
file_data = await get_data(
|
|||
|
table_name='files',
|
|||
|
query_filter={'id': file['file_id']}
|
|||
|
)
|
|||
|
await bot.send_document(
|
|||
|
chat_id=moderator[0]['telegram_id'],
|
|||
|
document=FSInputFile(FILES_PATH + file_data[0]['file'])
|
|||
|
)
|
|||
|
last_msg = await bot.send_message(
|
|||
|
chat_id=moderator[0]['telegram_id'],
|
|||
|
text=choose_action_text,
|
|||
|
reply_markup=choose_action_ikb(
|
|||
|
idea_id=idea_id,
|
|||
|
msg_id=0
|
|||
|
)
|
|||
|
)
|
|||
|
await bot.edit_message_reply_markup(
|
|||
|
message_id=last_msg.message_id,
|
|||
|
chat_id=moderator[0]['telegram_id'],
|
|||
|
reply_markup=choose_action_ikb(
|
|||
|
idea_id=idea_id,
|
|||
|
msg_id=last_msg.message_id
|
|||
|
)
|
|||
|
)
|
|||
|
moderator_user_data = await get_data(
|
|||
|
table_name='users',
|
|||
|
query_filter={'id': moderator_id['user_id']}
|
|||
|
)
|
|||
|
await notify(
|
|||
|
user_id=moderator_user_data[0]['external_id'],
|
|||
|
message='Новая быстрая НеоИдея!'
|
|||
|
)
|
|||
|
|
|||
|
except Exception as e:
|
|||
|
logging.error(e)
|
|||
|
|
|||
|
curators = await get_data(
|
|||
|
table_name='user_to_roles',
|
|||
|
query_filter={'role_id': ROLE_CURATOR_ID}
|
|||
|
)
|
|||
|
for curator in curators:
|
|||
|
try:
|
|||
|
user_data = await get_data(
|
|||
|
table_name='users',
|
|||
|
query_filter={'id': curator['user_id']}
|
|||
|
)
|
|||
|
await notify(
|
|||
|
user_id=user_data[0]['external_id'],
|
|||
|
message='Новая быстрая НеоИдея!'
|
|||
|
)
|
|||
|
except Exception as e:
|
|||
|
logging.error(f'не могу отправить уведомление куратору о новой идее {e}')
|
|||
|
|
|||
|
|
|||
|
async def accept_notify(author_name: str, responsible_id: str, author_id: int) -> None:
|
|||
|
"""
|
|||
|
Уведомляет куратора и автора о принятии идеи
|
|||
|
:param responsible_id: ID кому передают идею
|
|||
|
:param author_name: Имя автора идеи
|
|||
|
:param author_id: ID автора
|
|||
|
:return:
|
|||
|
"""
|
|||
|
responsible_data = await get_data(
|
|||
|
table_name='users',
|
|||
|
query_filter={'id': responsible_id}
|
|||
|
)
|
|||
|
notify_text = notify_curator_text.format(
|
|||
|
author_name=author_name,
|
|||
|
responsible_name=responsible_data[0]['full_name']
|
|||
|
)
|
|||
|
curators = await get_data(
|
|||
|
table_name='user_to_roles',
|
|||
|
query_filter={'role_id': ROLE_CURATOR_ID}
|
|||
|
)
|
|||
|
|
|||
|
for curator in curators:
|
|||
|
try:
|
|||
|
user_data = await get_data(
|
|||
|
table_name='users',
|
|||
|
query_filter={'id': curator['user_id']}
|
|||
|
)
|
|||
|
await notify(
|
|||
|
user_id=user_data[0]['external_id'],
|
|||
|
message=notify_text
|
|||
|
)
|
|||
|
await bot.send_message(
|
|||
|
chat_id=user_data[0]['telegram_id'],
|
|||
|
text=notify_text
|
|||
|
)
|
|||
|
except Exception as e:
|
|||
|
logging.error(f'не могу отправить уведомление куратору о принятии идеи {e}')
|
|||
|
|
|||
|
try:
|
|||
|
author_data = await get_data(
|
|||
|
table_name='users',
|
|||
|
query_filter={'id': author_id}
|
|||
|
)
|
|||
|
await notify(
|
|||
|
user_id=author_data[0]['external_id'],
|
|||
|
message=notify_author_text
|
|||
|
)
|
|||
|
await bot.send_message(
|
|||
|
chat_id=author_data[0]['telegram_id'],
|
|||
|
text=notify_author_text
|
|||
|
)
|
|||
|
except Exception as e:
|
|||
|
logging.error(f'Не смог отправить уведомление автору идеи {e}')
|
|||
|
|
|||
|
|
|||
|
async def confirm_notify(author_name: str, responsible_id: str, author_id: int) -> None:
|
|||
|
"""
|
|||
|
Уведомляет куратора и автора о согласовании идеи
|
|||
|
:param responsible_id: ID кому передают идею
|
|||
|
:param author_name: Имя автора идеи
|
|||
|
:param author_id: ID автора
|
|||
|
:return:
|
|||
|
"""
|
|||
|
responsible_data = await get_data(
|
|||
|
table_name='users',
|
|||
|
query_filter={'id': responsible_id}
|
|||
|
)
|
|||
|
notify_text = confirm_notify_curator_text.format(
|
|||
|
author_name=author_name,
|
|||
|
responsible_name=responsible_data[0]['full_name']
|
|||
|
)
|
|||
|
curators = await get_data(
|
|||
|
table_name='user_to_roles',
|
|||
|
query_filter={'role_id': ROLE_CURATOR_ID}
|
|||
|
)
|
|||
|
|
|||
|
for curator in curators:
|
|||
|
try:
|
|||
|
user_data = await get_data(
|
|||
|
table_name='users',
|
|||
|
query_filter={'id': curator['user_id']}
|
|||
|
)
|
|||
|
await notify(
|
|||
|
user_id=user_data[0]['external_id'],
|
|||
|
message=notify_text
|
|||
|
)
|
|||
|
await bot.send_message(
|
|||
|
chat_id=user_data[0]['telegram_id'],
|
|||
|
text=notify_text
|
|||
|
)
|
|||
|
except Exception as e:
|
|||
|
logging.error(f'не могу отправить уведомление куратору о принятии идеи {e}')
|
|||
|
|
|||
|
try:
|
|||
|
author_data = await get_data(
|
|||
|
table_name='users',
|
|||
|
query_filter={'id': author_id}
|
|||
|
)
|
|||
|
await notify(
|
|||
|
user_id=author_data[0]['external_id'],
|
|||
|
message=notify_author_text
|
|||
|
)
|
|||
|
await bot.send_message(
|
|||
|
chat_id=author_data[0]['telegram_id'],
|
|||
|
text=notify_author_text
|
|||
|
)
|
|||
|
except Exception as e:
|
|||
|
logging.error(f'Не смог отправить уведомление автору идеи {e}')
|