Initial Commit

This commit is contained in:
Zimmerberger Markus
2022-01-21 17:39:39 +01:00
commit e03f3aae52
10 changed files with 602 additions and 0 deletions
+219
View File
@@ -0,0 +1,219 @@
#!/usr/bin/python3
# import work-log entries from elsap csv
# avoid multiple logging
# TODO: log completely
# zisco 2021-10-28 09:33
import os, shutil
import logging
from types import ClassMethodDescriptorType
from jira import JIRA, Issue, Comment, exceptions, JIRAError
import re
import csv
from numpy import single
# import xlsxwriter
import pandas as pd
from pandas.core.dtypes.missing import notnull
import json
from pandas.core.frame import DataFrame
from requests.sessions import codes
def process_elsap_file(filename):
data = pd.read_excel(filename)
df = pd.DataFrame(data, columns=['Mitarbeiter','Datum','Menge.1','Benutzerfeld']) # dtype={'Mitarbeiter': str, 'Menge.1': float, 'Benutzerfeld': str})
df = df.dropna()
#filtered_df = df.loc[(df['Datum'] >= '2021-10-01')
# & (df['Datum'] < '2021-11-02')]
df = df.loc[(df['Datum'] <= '2021-11-07')]
logging.info('Consider dates <= {}'.format('2021-11-07'))
df['doit'] = True
df['new'] = False
df['del'] = False
df['JIRA'] = ''
logging.info("Initial DataFrame size is {} rows".format(len(df.index)))
df = single_line_dataframe(df)
logging.info("Adapted DataFrame size is {} rows".format(len(df.index)))
real = False
for index, row in df.iterrows():
# search for corresponding JIRA-issue
issue_str = "WRGWR-{}".format(row['JIRA'])
print("Working on {}".format(issue_str))
logging.info("Working on {}".format(issue_str))
try:
worklogs = jira_server.worklogs(issue_str)
except JIRAError as e:
logging.error('JIRA-Iyssue {} not found! (status: {} text: {})'.format(issue_str, e.status_code, e.text))
continue
# probably work is already logged?
for worklog in worklogs:
# get corresponding user
jira_worklog_user = worklog.author.key
elsap_user = user_array[row['Mitarbeiter']]
if jira_worklog_user==elsap_user:
if not confirm_prompt("User {} has already logged, still add worklog?".format(row['Mitarbeiter'])):
df.at[index,'doit'] = False
logging.info("No worklog wanted!")
issue = jira_server.issue(issue_str)
originalEstimate = xsp(issue.fields.timeoriginalestimate)
# TODO: Check if original time estimated set? (and, if it set well!)
if hasattr(issue.fields, 'customfield_10022'):
storypoints = xsp(issue.fields.customfield_10022)
if (storypoints/2*28800) != originalEstimate:
# adjust
if confirm_prompt("Adjust original-estimate with storypoints? (old {}, new {})".format(originalEstimate, storypoints/2*28800)):
if real == True:
issue.fields.timeoriginalestimate = storypoints/2*28800 # is that needed?
issue.update(fields={'timetracking': {'originalEstimate': '{}d'.format(storypoints/2)}})
# print("Old {} new {}".format(storypoints, issue.fields.timeoriginalestimate))
# logging.info("Old estimation {} should be changed to {} days (based on {} storypoints)".format(originalEstimate, storypoints/2, storypoints))
logging.info("Old estimation {} changed to {} days (based on {} storypoints)".format(originalEstimate, storypoints/2, storypoints))
if row['doit'] == True:
if confirm_prompt("Add worklog for {}? ".format(issue_str)):
if real == True:
jira_server.add_worklog(issue_str, timeSpent="{}h".format(row['Menge.1']), user="{} worked on issue {} {} hours at {}".format(row['Mitarbeiter'], issue_str, row['Menge.1'], row['Datum']))
# print(row['Datum'],row['Mitarbeiter'],row['Menge.1'],row['Benutzerfeld'],row['JIRA'])
logging.info("{} worked {} hours at {}".format(row['Mitarbeiter'], row['Menge.1'], row['Datum']))
def confirm_prompt(question: str) -> bool:
reply = None
while reply not in ("", "y", "n"):
reply = input(f"{question} (Y/n): ").lower()
return (reply in ("", "y"))
def extract_jira_issues(comment):
if pd.notna(comment):
return re.findall(r'WRGWR-\d+', comment)
"""
# possible values: Refinement (2), 1000 (2,5), Jour Fixe(1)
# 819(1),798(2),888(2), Meeting (1.5)
commentSplit = comment.split('),')
bookedJira = {}
singleJira = []
for singleItem in commentSplit:
# a valid single item is a pair of two numerical values
singleJira = re.findall(r'\d+', singleItem)
if len(singleJira) == 2:
bookedJira[singleJira[0]] = singleJira[1] """
# return bookedJira
def single_line_dataframe(df) -> DataFrame:
for index, row in df.iterrows():
issue_number = extract_jira_issues(row['Benutzerfeld'])
if issue_number:
if len(issue_number) > 1:
time = xsp(row['Menge.1'])/len(issue_number) # TODO: Consider possibility of given notation: "758 (2), 759 (1)"
df.at[index, 'del'] = True
for single_issue in issue_number: # issue_number[1:]
new_rows = []
# fix time of first entry, add as much as needed new lines
row.loc['Menge.1'] = time
row.loc['JIRA'] = single_issue
row.loc['new'] = True
new_rows.append(row)
df = df.append(pd.DataFrame(new_rows, columns=df.columns), ignore_index=True) # .reset_index()
else:
df.at[index, 'JIRA'] = issue_number
else:
df.at[index, 'doit'] = False
# drop all to-be deleted rows
indexNames = df[df['del'] == True].index
df.drop(indexNames , inplace=True)
# drop all non-doit
indexNames = df[df['doit'] == False].index
df.drop(indexNames , inplace=True)
return df
# map elsap-users to jira-users
# input_file = open('elsap_to_jira_user.json', encoding="utf-8")
userjson = '{"Kratochvil Jakub":"JIRAUSER16603","Zimmerberger Markus":"JIRAUSER17211","Cervenka Raimund":"JIRAUSER14400","Reischitz Ulf":"reu9001","Kremser Peter":"krp9002","Thüringer Helfried":"JIRAUSER15724","Blagojevic Nikolina":"JIRAUSER17212","Unfried Daniel":"und9001","Stefan Ion-Christian":"JIRAUSER16518"}'
user_array = json.loads(userjson)
# print(type(user_array))
logging.basicConfig(filename='elsap_importer.log',
filemode='a',
format='%(asctime)s - %(levelname)s: %(message)s',
level=logging.INFO,
encoding='utf-8')
host = "https://jira.wien.gv.at/"
pat = "OTAyMTM3MjY0MjE0Ovz6bu0ti1TlEdSegmmiWiJ2wGeD"
headers = JIRA.DEFAULT_OPTIONS["headers"].copy()
headers["Authorization"] = f"Bearer {pat}"
jira_server = JIRA(server=host, options={"headers": headers})
logging.info("Connection to JIRA established")
xsp = lambda s: s or 0
# open elsap-xlsx
with os.scandir(r'C:\Users\zim9003\Documents\reports') as it:
for entry in it:
if entry.name.endswith(".xlsx") and entry.is_file():
logging.info('Processing file {}'.format(entry.path))
process_elsap_file(entry.path)
# move to done
logging.info('Moved file to done -> {}'.format(entry.name))
shutil.move(entry.path, r'C:\Users\zim9003\Documents\reports\done\{}'.format(entry.name))
# issues_Jql = jira_server.search_issues('cf[10022] is not EMPTY AND labels not in (Refinement23092021, hotfix0921) AND status not in (Done) and key not in (wrgwr-929)', expand='changelog')
# issues_Jql = jira_server.search_issues('status not in (Done)', expand='changelog')
""" issues_Jql = jira_server.search_issues('key in (wrgwr-773)', expand='changelog')
xsp = lambda s: s or 0
sp_sum = 0
issue: Issue
for issue in issues_Jql:
logging.info("Working on {}".format(issue.key))
sp = 0
if hasattr(issue.fields, 'customfield_10022'):
sp = xsp(issue.fields.customfield_10022)
sp_sum += sp
# log old values
print(sp, sp/8)
originalEstimate = xsp(issue.fields.timeoriginalestimate)
logging.info("Estimation-system change: Old Story Points {} -> new Story Points {}".format(sp, sp/8))
if (originalEstimate != 0) and (originalEstimate / 14400) != sp:
# probably already adapted? Search for activity 'updated the Story Points'
doChange = True
for history in issue.changelog.histories:
if doChange==False:
break
if (history.author.key=='JIRAUSER17211'):
for item in history.items:
if (item.field=='Story Points'):
doChange = False
break
if doChange:
# update story-points
try:
issue.update(fields={'customfield_10022': originalEstimate / 14400})
comment = jira_server.add_comment(issue, "Estimation-system change: Old Story Points {} -> new Story Points {}".format(sp, sp/8))
except exceptions.JIRAError:
logging.error("Issue {} has no (visible) Story Points-attribute".format(issue.key))
finally:
print('Done {}'.format(issue.key)) """