Untitled
unknown
plain_text
2 years ago
12 kB
10
Indexable
from jupytercloud.library import get_secret
import requests
import json
import pandas as pd
import numpy as np
from openpyxl import load_workbook
from io import BytesIO
import ast
# Получение токена из секрета
TrackerOauthToken = get_secret('sec-01hbdac4pph2h48dwacme1x15h')
TOKEN = TrackerOauthToken.get('TOKEN')
# Параметры запроса
HEADERS = {
'Authorization': f'OAuth {TOKEN}',
'Content-Type': 'application/json'}
URL = 'https://st-api.yandex-team.ru/v2/issues/'
# Фильтрация тикетов через query
start_date = "01.09.2023"
end_date = "30.09.2023"
query = f'Queue: Заявки ("Новая Зарплата": notEmpty() OR Теги:Массовое_повышение OR "Новая тарифная ставка":notEmpty()) (Статус: ! "Отмена заявки" Статус: !"В работе" Статус: !Проверка Статус: !"Ждем подтверждения" Статус: !"Согласование в HR") Резолюция: !Некорректный Резолюция: ! "Не будет исправлено" Резолюция: ! Duplicate Резолюция: ! "Дубликат (подзадача)" "Дата повышения": >= {start_date} "Дата повышения": < {end_date}'
filter = {
'filter': {
},
'query': f'{query}'
}
# Список для всех тикетов, полученных из запроса
data = []
# Первый запрос
response_scroll = requests.post(f'{URL}_search?scrollType=unsorted&perScroll=1000', headers=HEADERS, data=json.dumps(filter))
# Cледующие запросы
if response_scroll.status_code == 200:
try:
while True:
response_data = response_scroll.json()
data.extend(response_data)
# Если прокрутка еще не закончена, возвращаются заголовки X-Scroll-Id и X-Scroll-Token,
# значения которых можно передать в параметрах scrollId и scrollToken соответственно для получения следующей страницы результатов.
X_Scroll_Id = response_scroll.headers.get('X-Scroll-Id')
X_Scroll_Token = response_scroll.headers.get('X-Scroll-Token')
if not X_Scroll_Id or not X_Scroll_Token:
break
# Последующие запросы, состаленные используюя scrollId и scrollToken из заголовков предыдущих запросов
response_scroll = requests.post(f'{URL}_search?scrollId={X_Scroll_Id}&scrollToken={X_Scroll_Token}', headers=HEADERS, data=json.dumps(filter))
except json.JSONDecodeError as e:
print(f'Failed to decode JSON: {e}')
except:
print(f'Request error: {response_scroll.status_code}')
# Данные по полям тикетов SALARY
keys = []
employees = []
logins = []
summaries = []
statuses = []
assignees = []
dates = []
bp_numbers = []
current_tariff_rates = []
new_tariff_rates = []
current_salaries = []
new_salaries = []
organizations = []
entities = []
transactions = []
systems = []
currencies = []
components = []
# Данные по тикетам с массовым повышением SALARY
mass = []
for ticket in data:
tag = [tag for tag in ticket.get('tags', {})]
if "Массовое_повышение" not in tag:
keys.append(ticket.get('key', {}))
employees.append(ticket.get('employee', {}).get('display', {}))
logins.append(ticket.get('employee', {}).get('id', {}))
summaries.append(ticket.get('summary', {}))
statuses.append(ticket.get('status', {}).get('display', {}))
assignees.append(ticket.get('assignee', {}).get('display', {}))
dates.append(ticket.get('raiseDate', {}))
bp_numbers.append(ticket.get('bpNumber', {}))
current_tariff_rates.append(ticket.get('urrentTariffRate', {}))
new_tariff_rates.append(ticket.get('rateTariff', {}))
current_salaries.append(ticket.get('currentSalary', {}))
new_salaries.append(ticket.get('newSalary', {}))
organizations.append(ticket.get('organization', {}))
entities.append(ticket.get('legalEntity2', {}).get('display', {}))
transactions.append(ticket.get('5fedc3773bcd8c3a56eb7ef5--priznakSdelka', {}))
systems.append(ticket.get('salarySystem', {}))
currencies.append(ticket.get('currency', {}))
components.append([component['display'] for component in ticket.get('components', {})])
else:
key_mass = ticket.get('key', {})
summary_mass = ticket.get('summary', {})
status_mass = ticket.get('status', {}).get('display', {})
assignee_mass = ticket.get('assignee', {}).get('display', {})
date_mass = ticket.get('raiseDate', {})
component_mass = [component['display'] for component in ticket.get('components', {})]
# Создаём словарь с данными по тикетам с массовым повышением
dict_mass = {'key': key_mass, 'summary': summary_mass, 'status': status_mass, 'assignee': assignee_mass, 'date': date_mass, 'component': component_mass}
mass.append(dict_mass)
with pd.ExcelWriter('Кадровая сверка.xlsx', engine='xlsxwriter') as writer:
# Создаём датафрейс с данными по тикетам
df_main = pd.DataFrame({
'Ключ тикета': keys,
'Сотрудник': employees,
'Логин': logins,
'Задача': summaries,
'Статус': statuses,
'Исполнитель': assignees,
'Дата повышения': dates,
'Номер БП': bp_numbers,
'Текущая тарифная ставка': current_tariff_rates,
'Новая тарифная ставка': new_tariff_rates,
'Текущая зарплата': current_salaries,
'Новая зарплата': new_salaries,
'Оклад': None,
'Валюта': None,
'Ставка': None,
'Организация': organizations,
'Юридическое лицо 2.0': entities,
'Признак сделка': transactions,
'Система оплаты труда': systems,
'Компоненты': components
})
# Разбиваем столбец 'Новая зарплата' на 'Оклад', 'Валюта', 'Ставка'
# Орабатываем исключения в столбце 'Оклад'
# 'Компоненты' представляем в виде строки
df_main['Оклад'] = df_main['Новая зарплата'].str.extract(r'(\d[\d\s.,]*)')
df_main['Оклад'] = df_main['Оклад'].str.replace(r'\s,', '', regex=True).str.replace(',', '.', regex=True)
df_main['Валюта'] = df_main['Новая зарплата'].str.extract(r'([A-Z]+)').fillna('')
df_main['Ставка'] = df_main['Новая зарплата'].str.extract(r'\(([^)]+)\)')
df_main['Ставка'] = df_main['Ставка'].apply(lambda x: None if x == 'None' else x)
df_main['Компоненты'] = df_main['Компоненты'].apply(lambda x: ', '.join(map(str, x)))
df_main = df_main.replace([{}], value=np.NaN)
df_main.fillna('', inplace=True)
df_main.index = pd.RangeIndex(1, len(df_main)+1, name='№')
# Сохраняем датафрейм с данными по всем тикетам кроме массовых на первом листе эксель 'Выгрузка'
df_main.to_excel(writer, sheet_name='Выгрузка', index=True, header=True)
for mass_ticket in mass:
key = mass_ticket.get('key')
summary = mass_ticket.get('summary')
status = mass_ticket.get('status')
assignee = mass_ticket.get('assignee')
date = mass_ticket.get('date')
component = [component for component in mass_ticket.get('component')]
# Запрос для получения списка вложений в массовых тикетах
response_mass = requests.get(f'{URL}{key}/attachments', headers=HEADERS)
attach_id = response_mass.json()[0].get('id')
attach_name = response_mass.json()[0].get('name')
# Запрос для получения ссылки на скачивание кокретного вложения
response_attach = requests.get(f'{URL}{key}/attachments/{attach_id}/{attach_name}', headers=HEADERS)
try:
# Содержимое вложения представляем в виде датафрейма
df_mass = pd.read_excel(BytesIO(response_attach.content), skiprows=[0], header=0)
# Дополняем вложение данными из массового тикета
df_mass['Ссылка на тикет'] = key
df_mass.insert(1, 'Задача', summary)
df_mass.insert(2, 'Исполнитель', assignee)
df_mass.insert(3, 'Статус', status)
df_mass.insert(4, 'Дата повышения', date)
df_mass.insert(5, 'Компоненты', str(component))
df_mass['Компоненты'] = df_mass['Компоненты'].apply(lambda x: ', '.join(map(str, ast.literal_eval(x))))
df_mass.index = pd.RangeIndex(1, len(df_mass)+1, name='№')
# Сохраняем датафрейм с данными по массовым тикетам на листах эксель
df_mass.to_excel(writer, sheet_name=f'Mass_{key}', index=True)
except Exception as e:
print(f'Error reading attached file: {e}', mass_ticket)
# Запрос для получения комментариев к массовому тикету
response_comment = requests.get(f'{URL}{key}/comments', headers=HEADERS)
try:
comment_list = []
comments = response_comment.json()
for comment in comments:
author = comment.get('createdBy', {}).get('display', {})
date = comment.get('createdAt', {})
text = comment.get('text', {})
# Создаём словарь с данными по всем комментариям к тикету
dict = {'Автор': author, 'Создан': date, 'Текст': text}
comment_list.append(dict)
# Создаём датафрейс с данными по комментариям к массовому тикету
df_comm = pd.DataFrame(comment_list)
df_comm.index = pd.RangeIndex(1, len(df_comm)+1, name='№')
# Сохраняем датафрейм с комментариями к массовым тикетам на листах эксель
df_comm.to_excel(writer, sheet_name=f'Comments_{key}', index=True)
except Exception as e:
print(f'Error reading comments: {e}', mass_ticket) Editor is loading...