示例#1
0
def get_user_info(user_id: int, sid: str = None) -> dict:
    mined_users = [
        row["UserID"] for row in Database.query('SELECT * FROM "MinedUsers"')
    ]

    if user_id not in mined_users:
        mine_user_info(user_id, sid)

    # get user days count in dataset (except weekends)
    total_days = Database.query_row(
        'select "TotalDays" from  "MinedUsers" where "UserID" = %s',
        (user_id, ))['TotalDays']

    result = {}

    result['user_responsibility'] = __calculate_user_responsibility(user_id)
    result['user_sociability'] = __calculate_user_sociability(
        user_id, total_days)
    result['user_procrastination'] = __calculate_user_procrastination(
        user_id, total_days)
    result['user_often_leaving'] = __calculate_user_leaving(user_id)
    result['user_punctuality'] = __calculate_user_punctuality(user_id)
    result['user_leaving_state'] = __calculate_user_leaving_state(user_id)

    return result
def __get_user_activity(user_id: int, sid: str, datelist: list = None):
    """
    Получает данные активности пользователя и сохраняет их в базу.

    :param user_id: идентификатор пользователя, по которому необходимо собрать статистику
    :type user_id: int
    :param datelist: список дат по которым необходимо собрать статистику, defaults to None
    :param datelist: list, optional
    """

    insert_query = """
        INSERT INTO "UserActivity"("UserID", "Date", "Category", "Useful", "WastedTime")
        VALUES (%s, %s, %s, %s, %s);
    """
    if not datelist:
        datelist = __get_date_range(date.today())

    for cur_date in datelist:

        rpc_result = SabyInvoker.invoke('Report.PersonProductivityStatistic',
                                        sid,
                                        Фильтр=SabyFormatsBuilder.build_record(
                                            {
                                                "Date": cur_date,
                                                "Person": user_id
                                            }),
                                        Сортировка=None,
                                        Навигация=None,
                                        ДопПоля=[])

        person_activities = [
            activity for activity in rpc_result['rec'] if activity['Parent@']
        ] if rpc_result else []

        for activity in person_activities:
            # write user activity
            Database.query(
                insert_query,
                (user_id, cur_date, activity['Name'], activity['Useful'],
                 __convert_magic_string(activity['Duration'])))

        # get user calls
        out_calls = __get_user_out_calls(user_id, cur_date, sid)

        Database.query(
            insert_query,
            (user_id, cur_date, "Звонки СБИС", 0, out_calls['duration']))
def __get_user_neural_data(user_id: int, sid: str):
    # get data from last month
    last_days_range = __get_date_range(date.today(), 1)
    last_count, last_time = __get_user_calls(user_id, last_days_range, sid)
    last_overwork = __get_user_overwork(user_id, last_days_range, sid)
    # get data from first 2 months
    first_start_day = date.today() - relativedelta(months=1)
    first_days_range = __get_date_range(first_start_day, 2)
    first_count, first_time = __get_user_calls(user_id, first_days_range, sid)
    first_overwork = __get_user_overwork(user_id, first_days_range, sid)

    Database.query(
        """
        INSERT INTO "UsersNeuralData"(
            "UserID", "UserFirstCalls", "UserLastCalls", "UserFirstDuration", "UserLastDuration", "UserFirstOverwork", "UserLastOverwork"
        )
        VALUES (%s, %s, %s, %s, %s, %s, %s);
        """, (user_id, first_count, last_count, first_time, last_time,
              first_overwork, last_overwork))
def __get_user_location_and_overwork(user_id: int,
                                     sid: str,
                                     datelist: list = None):
    """
    Получает данные местонахождения пользователя и сохраняет их в базу.

    :param user_id: идентификатор пользователя, по которому необходимо собрать статистику
    :type user_id: int
    :param datelist: список дат по которым необходимо собрать статистику, defaults to None
    :param datelist: list, optional
    """
    if not datelist:
        datelist = __get_date_range(date.today())

    for cur_date in datelist:

        rpc_result = __get_user_day_location(user_id, cur_date, sid)
        entrances = [
            entity for entity in rpc_result['activity_detail']['rec']
            if entity['Описание'] == 'entrance'
        ]

        for entrance in entrances:
            Database.query(
                """
                INSERT INTO "UserLocation" ("UserID", "DateTime", "Status")
                VALUES (%s, %s, %s);
                """, (user_id, entrance["ВремяНачало"], entrance["Действие"]))

        # Смотрим всю активность
        activity_summary = rpc_result.get('activity_summary')

        # Выбираем необходимое время работы
        need_time_str = activity_summary.get('ВремяРаботыГрафик', '00:00:00')
        # Выбираем фактически сколько сотрудник отработал
        fact_time_str = activity_summary.get('ВремяРаботы', '00:00:00')

        Database.query(
            """
            INSERT INTO "UserOverwork" ("UserID", "Date", "Overwork")
            VALUES (%s, %s, %s);
            """, (user_id, cur_date,
                  __calculate_overwork(need_time_str, fact_time_str)))
def mine_user_info(user_id: int, sid: str):
    dates = __get_date_range(date.today())
    # Get user location and overwork
    __get_user_location_and_overwork(user_id, sid, dates)

    # Get user activity
    __get_user_activity(user_id, sid, dates)

    # Get user plan percent
    __get_user_plan_percent(user_id, sid)

    # Prepare neural dataset
    __get_user_neural_data(user_id, sid)
    # Add user id in mined persons
    Database.query(
        """
            INSERT INTO "MinedUsers"("UserID", "TotalDays")
            VALUES (%s, %s);
        """, (user_id, len(dates)))

    # Apply database changes
    Database.commit_changes()
def __get_user_plan_percent(user_id: int, sid: str, month_count: int = 3):
    """
    Получает данные по выполнению плана за указанный период и сохраняет их в базу.

    :param user_id: идентификатор пользователя, по которому необходимо собрать статистику
    :type user_id: int
    :param month_count: кол-во месяцев за которое надо собрать статистику, defaults to 3
    :type user_id: int, optional
    """
    today = date.today()
    start_date = date(year=today.year, month=today.month,
                      day=1) - relativedelta(months=month_count)
    end_date = date(year=today.year, month=today.month,
                    day=1) - relativedelta(days=1)

    rpc_result = SabyInvoker.invoke('ПланРабот.ПунктыНаКарточкеСотрудника',
                                    sid,
                                    Фильтр=SabyFormatsBuilder.build_record({
                                        "ДатаНачала":
                                        str(start_date),
                                        "ДатаОкончания":
                                        str(end_date),
                                        "ФильтрПериод":
                                        "Период",
                                        "ЧастноеЛицо":
                                        user_id
                                    }),
                                    Сортировка=None,
                                    Навигация=None,
                                    ДопПоля=[])
    percent_structure = rpc_result.get('outcome', None) if rpc_result else None

    if percent_structure:
        Database.query(
            """
                INSERT INTO "UserPlanPercent"("UserID", "PlanPercent")
                VALUES (%s, %s);
                """, (user_id, percent_structure['Процент']))
示例#7
0
def __calculate_user_punctuality(user_id: int) -> int:
    # !Settings
    # max deviation minutes per day (setting)
    MAX_DEVIATION = 30

    user_incoming = Database.query(
        """
        With "Dates" as (
            select "DateTime"::date as "Date"
            from "UserLocation"
            Where "UserID" = %s and "Status" = 1
            group by "Date"
        )
        select dates."Date", min(main."DateTime"::time) as "ComingTime"
        from "UserLocation" as main
        inner join "Dates" as dates
            on dates."Date" = main."DateTime"::date
        group by dates."Date"
        order by dates."Date"
        """, (user_id, ))
    if user_incoming:
        # get user incoming times as seconds
        timelist = [row['ComingTime'] for row in user_incoming]
        timelist = [
            timedelta(hours=x.hour, minutes=x.minute,
                      seconds=x.second).total_seconds() for x in timelist
        ]

        # convert max deviation to seconds
        time_max_deviation = timedelta(minutes=MAX_DEVIATION).total_seconds()

        # calculate average tive with deviation
        k_mean = kmeans(timelist, 1)[0][0]
        max_time = k_mean + time_max_deviation
        min_time = k_mean - time_max_deviation

        # find punctual points
        punctual = [
            time for time in timelist if time > min_time and time < max_time
        ]
        return int(round(len(punctual) / len(timelist) * 10))

    return -1