Exemple #1
0
def info(msg: types.Message):
    if not is_admin(msg.from_user):
        bot.send_message(msg.from_user.id, 'Вы не являетесь админом.')
        return

    def format_executor(ex: Executor) -> str:
        return f"  [{ex.intraservice_user.name}](tg://user?id={ex.telegram_user.user_id}) \n"

    def format_task(tsk: IntraserviceTask) -> str:
        task_url = api.new_api.get_task_url(tsk.id)
        return f" [#{tsk.id}]({task_url})"

    def format_executor_with_task(ex: Executor) -> str:
        tsk = ex.intraservice_task_active
        if not tsk:
            return f"  [{ex.intraservice_user.name}](tg://user?id={ex.telegram_user.user_id})\n"
        else:
            task_url = api.new_api.get_task_url(tsk)
            return f"  [{ex.intraservice_user.name}](tg://user?id={ex.telegram_user.user_id}) " \
                f"([#{tsk.id}]({task_url})\n"

    ready_executors = get_ready_executors()
    ready_executors_list = ''
    for executor in ready_executors:
        ready_executors_list += format_executor(executor)

    working_executors = get_working_executors()
    working_executors_list = ''
    for executor in working_executors:
        working_executors_list += format_executor_with_task(executor)

    opened_tasks = get_opened_tasks()
    opened_tasks_list = ''
    for task in opened_tasks:
        opened_tasks_list += format_task(task)
    if opened_tasks:
        opened_tasks_list += '\n'

    mass_tasks = get_mass_tasks()
    mass_tasks_list = ''
    for task in mass_tasks:
        mass_tasks += format_task(task)
    if mass_tasks:
        mass_tasks_list += '\n'

    bot.send_message(
        msg.from_user.id,
        r.INFO_MESSAGE.format(
            ready_executors=f"{len(ready_executors)}:" if ready_executors else "нет",
            ready_executors_list=ready_executors_list,
            working_executors=f"{len(working_executors)}:" if working_executors else "нет",
            working_executors_list=working_executors_list,
            opened_tasks=f"{len(opened_tasks)}:" if opened_tasks else "нет",
            opened_tasks_list=opened_tasks_list,
            blockage_exist="Завал есть" if len(opened_tasks) >= 5 else "Завала нет",
            mass_tasks=f"len(mass_tasks):" if mass_tasks else "нет",
            mass_tasks_list=mass_tasks_list
        ),
        parse_mode="Markdown"
    )
Exemple #2
0
def pin_critical_task(executor: Executor, new_task: IntraserviceTask):
    old_task = executor.intraservice_task_active
    executor.intraservice_task_active = new_task
    executor.save()
    new_task.long_execution_notification = timezone.now()
    new_task.executor_notification_count = 0
    new_task.admin_notification = timezone.now()
    new_task.admin_notification_count = 0
    new_task.save()
    old_task.postponed_type = POSTPONED_TYPE['Критическая завка']
    old_task.postponed_executor = executor
    old_task.save()
    api.new_api.change_task(old_task.id,
                            status_id=TASK_STATUSES['Отложена'],
                            comment='Переведен на критическую заявку')
    api.new_api.change_task(new_task.id,
                            status_id=TASK_STATUSES['В работе'],
                            executor_ids=[executor.intraservice_user.id])
    old_url = api.new_api.get_task_url(old_task.id)
    new_url = api.new_api.get_task_url(new_task.id)
    bot.send_message(executor.telegram_user.user_id,
                     text=r.CHANGE_TO_CRITICAL_MESSAGE.format(
                         old_task_id=old_task.id,
                         new_task_id=new_task.id,
                         old_url=old_url,
                         new_url=new_url,
                         executors=len(get_ready_executors()),
                         open_tasks=len(get_opened_tasks()),
                         mass_tasks=len(get_mass_tasks())),
                     parse_mode='Markdown')
Exemple #3
0
def executor_ready(message):
    try:
        executor = Executor.objects.get(telegram_user__user_id=message.from_user.id)
    except ObjectDoesNotExist:
        bot.send_message(message.from_user.id, 'Вы не являетесь работником ТП.')
        return
    if executor.status == 'Не готов':
        logging.debug(f'Change status of {executor} to (Ready)!')
        executor.status = 'Готов'
        executor.last_status_change = timezone.now()
        executor.save()
        bot.send_message(executor.telegram_user.user_id,
                         text=r.EXECUTOR_READY.format(executors_ready=len(get_ready_executors())))
    elif executor.status == 'Готов':
        bot.send_message(executor.telegram_user.user_id,
                         text=r.EXECUTOR_READY.format(executors_ready=len(get_ready_executors())))
    elif executor.status == 'Занят':
        task = executor.intraservice_task_active
        task_url = api.new_api.get_task_url(task.id)
        bot.send_message(message.from_user.id,
                         text=r.EXECUTOR_HAVE_TASK.format(task_id=task.id, task_url=task_url,
                                                          open_tasks=len(get_ready_executors())),
                         parse_mode='Markdown')
Exemple #4
0
 def blockage_notify(self):
     # Оповещения о завалах
     if len(get_opened_tasks()) >= 5:
         if not self.blockage:
             self.blockage_start_time = timezone.now()
             if len(get_ready_executors()):
                 message_to_admins(
                     ('🆘 Начался завал в работе сотрудников ТП: '
                      'уже больше 5 открытых заявок и все сотрудники заняты'
                      ))
             else:
                 message_to_admins((
                     '🆘 Начался завал в работе сотрудников ТП: '
                     'уже больше 5 открытых заявок и все сотрудники отсутствуют'
                 ))
         self.blockage = True
     else:
         if self.blockage:
             message_to_admins('🆗 Закончился завал в работе сотрудников ТП')
             BlockageJournal.objects.create(
                 from_time=self.blockage_start_time, to_time=timezone.now())
         self.blockage = False
Exemple #5
0
    def run(self):
        logging.info("Start status listener thread")
        self.check_tasks_in_db()
        pool = ThreadPool(5)
        last_update = timezone.now() - timedelta(hours=6)
        new_update = None
        self.update_enable.set()
        while self.run_enabled:
            self.new_task_count = 0
            logging.debug('Enabled creating tasks!')
            self.create_task_enable.set()
            if new_update:
                time.sleep(
                    max(0, UPDATE_TIME - (new_update - last_update).seconds))
            else:
                time.sleep(UPDATE_TIME)
            self.update_enable.wait(UPDATE_TIME)
            logging.debug('Disabled creating tasks!')
            self.create_task_enable.clear()

            new_update = timezone.now()

            # получаем все изменения заданий
            logging.info('Get updates...')
            try:
                tasks_updates = api.get_tasks(last_update)
            except api.new_api.APIError as e:
                logging.error(e)
                tasks_updates = []
                updated = False
            else:
                updated = True
                logging.debug('Updates received!')

            # обработка обновлений
            for task in tasks_updates:
                self.processing_update(task)

            # проверка всех заданий
            logging.debug('Start sync tasks from db...')
            start_time = time.time()
            pool.map(self.task_sync,
                     list(IntraserviceTask.objects.filter(~Q(status=29))))

            logging.debug('Finish sync tasks from db! (' +
                          str(time.time() - start_time) + ' seconds)')

            # Смена статуса у подзадач
            for mass_task in IntraserviceTask.objects.filter(~Q(
                    parent_id=None)):
                for task in IntraserviceTask.objects.filter(
                        parent_id=mass_task):
                    if task.status != mass_task.status:
                        logging.debug("Sync status of children {task}!")
                        api.new_api.change_task(
                            task.id,
                            status_id=mass_task.status,
                            comment='Синхронизация статуса с родителем.')

            # Удаляем сотрудников, у открытых заданий, которые были отложены
            for task in IntraserviceTask.objects.filter(
                    status=TASK_STATUSES['Открыта']).filter(
                        postponed_type=POSTPONED_TYPE['Отложена сотрудником']):
                remove_executor(task)

            # Проверяем сотрудников, которые отложили задания
            for ex in Executor.objects.filter(
                    intraservice_task_active__status=TASK_STATUSES["Отложена"]
            ):
                task_delay(ex)

            # Освобождаем работников, от решенных задач
            for ex in Executor.objects.filter(
                    Q(intraservice_task_active__status=TASK_STATUSES[
                        'Выполнена'])
                    | Q(intraservice_task_active__status=TASK_STATUSES[
                        'Отменена'])):
                close_task(ex)

            # Удаляем закрытые и отмененные задания
            for task in IntraserviceTask.objects.filter(  # type: IntraserviceTask
                    Q(status=TASK_STATUSES['Закрыта'])
                    | Q(status=TASK_STATUSES['Отменена'])):
                if not list(IntraserviceTask.objects.filter(parent=task)):
                    task.delete()

            # Освобождаем работников, у которых удалены задачи
            for ex in Executor.objects.filter(
                    intraservice_task_active=None).filter(status='Занят'):
                close_task(ex)

            # Оповещения о долгом выполнении
            for task in IntraserviceTask.objects.filter(~Q(executor=None) & Q(
                    executor__status='Занят')):
                executor = Executor.objects.get(intraservice_task_active=task)
                task_url = api.new_api.get_task_url(task.id)
                if (timezone.now() - task.long_execution_notification
                    ).seconds > 60 * NOTIFY_TASK_MIN:
                    bot.send_message(
                        executor.telegram_user.user_id,
                        text=r.LONG_WORK_EXECUTOR_NOTIFICATION.format(
                            task_id=task.id,
                            task_url=task_url,
                            NOTIFY_TASK_MIN=NOTIFY_TASK_MIN *
                            (task.executor_notification_count + 1)),
                        parse_mode='Markdown')
                    task.executor_notification_count += 1
                    task.long_execution_notification = timezone.now()
                if (timezone.now() -
                        task.admin_notification).seconds > 60 * MAX_TASK_MIN:
                    message_to_admins(
                        r.LONG_WORK_ADMIN_NOTIFICATION.format(
                            executor=executor.intraservice_user.name,
                            task_id=task.id,
                            task_url=task_url,
                            MAX_TASK_MIN=MAX_TASK_MIN *
                            (task.admin_notification_count + 1),
                            uid=executor.telegram_user.user_id))
                    task.admin_notification_count += 1
                    task.admin_notification = timezone.now()
                task.save()

            self.postponed_notify()

            # Объединяем похожие заявки от одного пользователя
            for task in IntraserviceTask.objects.filter(~Q(
                    telegram_client=None)).filter(parent_id=None).filter(
                        created__gte=last_update):  # type: IntraserviceTask
                try:
                    client = Client.objects.get(
                        intraservicetask=task)  # type: Client
                except ObjectDoesNotExist:
                    continue
                for c_task in IntraserviceTask.objects.filter(
                        telegram_client=client).filter(created__gte=(
                            timezone.now() - timedelta(minutes=60)
                        )).filter(~Q(description=None)).filter(
                            parent_id=None):  # type: IntraserviceTask
                    if task.id == c_task.id:
                        continue
                    for problem in MASS_PROBLEMS:  # type: IntraserviceTask
                        if problem in task.description and problem in c_task.description:
                            logging.debug(
                                f'Making {c_task} parent to {task}...')
                            task.parent_id = c_task
                            api.new_api.change_task(task.id,
                                                    parent_id=c_task.id)
                            task.save()
                            break

            self.group_mass_tasks()

            # Возвращаем заявки исполнителю
            for ex in Executor.objects.filter(~Q(
                    intraservice_task_active=None)).filter(
                        status='Готов').filter(last_status_change__lte=(
                            timezone.now() - timedelta(seconds=SEC_TO_PIN)
                        )).filter(
                            intraservice_task_active__parent__id=None).filter(
                                intraservice_task_active__executor_group=
                                EXECUTOR_GROUP_IDS['Техподдержка']):
                re_pin_to_task(ex)

            # Новые заявки и нет сотрудников
            if len(get_ready_executors()) == 0 and self.new_task_count:
                message_to_admins(r.NEW_TASK_NO_EXECUTORS)

            # Возвращаем отложеные (из-за критической заявки) заявки исполнителю (Критические)
            for task in IntraserviceTask.objects.filter(
                    postponed_type=POSTPONED_TYPE['Критическая завка']
            ).filter(priority=PRIORITY_STATUSES['Критический']).filter(
                    parent_id=None).filter(
                        executor_group=EXECUTOR_GROUP_IDS['Техподдержка']
                    ).filter():
                if task.postponed_executor.intraservice_task_active:
                    if task.postponed_executor.intraservice_task_active.priority != PRIORITY_STATUSES[
                        'Критический'] and task.postponed_executor.intraservice_task_active.postponed_type == \
                            POSTPONED_TYPE['Критическая завка']:
                        pin_critical_task(task.postponed_executor, task)
                else:
                    pin_to_task_after_critical(task)

            self.pin_critical_tasks()

            # Возвращаем отложеные (из-за критической заявки) заявки исполнителю
            for task in IntraserviceTask.objects.filter(
                    postponed_type=POSTPONED_TYPE['Критическая завка']
            ).filter(postponed_executor__status='Готов').filter(
                    parent_id=None).filter(
                        executor_group=EXECUTOR_GROUP_IDS['Техподдержка']
                    ).filter(~Q(status=TASK_STATUSES['Закрыта'])
                             & ~Q(status=TASK_STATUSES["Выполнена"])):
                pin_to_task_after_critical(task)

            self.pin_non_critical_tasks()

            self.blockage_notify()

            if updated:
                last_update = new_update
        pool.close()