Initial Commit
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
*.log
|
||||||
Vendored
+15
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Python: Current File",
|
||||||
|
"type": "python",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${file}",
|
||||||
|
"console": "integratedTerminal"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"python.pythonPath": "C:\\Python39\\python.exe"
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
from types import ClassMethodDescriptorType
|
||||||
|
from jira import JIRA
|
||||||
|
import csv
|
||||||
|
import xlsxwriter
|
||||||
|
|
||||||
|
# TODO: create excel!
|
||||||
|
|
||||||
|
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})
|
||||||
|
|
||||||
|
#jira_server = JIRA(basic_auth=("zim9003",""), options={'server': 'https://jira.wien.gv.at/'})
|
||||||
|
#jira_server = JIRA(basic_auth=("postman","OTAyMTM3MjY0MjE0Ovz6bu0ti1TlEdSegmmiWiJ2wGeD"), options={'server': 'https://jira.wien.gv.at/'})
|
||||||
|
|
||||||
|
#issues_Jql = jira_server.issue('WRGWR-828',expand='changelog')#pass one issue at the time
|
||||||
|
assignees = ["thh9001","krp9002","reu9001","und9001","krj0003","bln9001","ce39001","rab9001"]
|
||||||
|
for assignee in assignees:
|
||||||
|
issues_Jql = jira_server.search_issues('sprint = 1137 AND assignee = {} ORDER BY cf[10022] ASC'.format(assignee)) #, expand='changelog') # 1093
|
||||||
|
|
||||||
|
xsp = lambda s: s or 0
|
||||||
|
sp_sum = 0
|
||||||
|
for issue in issues_Jql:
|
||||||
|
sp = 0
|
||||||
|
if hasattr(issue.fields, 'customfield_10022'):
|
||||||
|
sp = xsp(issue.fields.customfield_10022)
|
||||||
|
sp_sum += sp
|
||||||
|
|
||||||
|
print('{}: {}, SP: {}'.format(issue.key, issue.fields.summary, sp))
|
||||||
|
|
||||||
|
print('Summe {}: {}'.format(assignee, sp_sum))
|
||||||
|
|
||||||
|
#print(issues_Jql)
|
||||||
|
# changelog = issues_Jql.
|
||||||
|
# count = 0
|
||||||
|
# for history in changelog.histories:
|
||||||
|
# for item in history.items:
|
||||||
|
# if item.field == 'status':
|
||||||
|
# if item.toString == "Reopened":
|
||||||
|
# count = count + 1
|
||||||
|
# print(count)
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
# find comments with estimations out of pre-planning
|
||||||
|
# zisco 2021-09-30 19:50
|
||||||
|
|
||||||
|
from types import ClassMethodDescriptorType
|
||||||
|
from jira import JIRA, Issue, Comment, exceptions
|
||||||
|
import re
|
||||||
|
import csv
|
||||||
|
import xlsxwriter
|
||||||
|
import logging
|
||||||
|
|
||||||
|
def get_assignee(type):
|
||||||
|
if type == 'Dev Backend':
|
||||||
|
return 'rab9001'
|
||||||
|
elif type == 'Dev Frontend':
|
||||||
|
return 'reu9001'
|
||||||
|
elif type[:14] == 'Test-Anpassung':
|
||||||
|
return 'ada9001'
|
||||||
|
|
||||||
|
def create_subtask(issue, parent, type, subtask_sp):
|
||||||
|
escaped = issue.fields.summary.replace('"','\\"')
|
||||||
|
print('summary ~ \"{}\"'.format(escaped))
|
||||||
|
|
||||||
|
subtask = jira_server.search_issues('summary ~ \"{} {}\"'.format(type, escaped))
|
||||||
|
if len(subtask) == 0:
|
||||||
|
#right = (comment_line.find(':')+2)-len(comment_line)
|
||||||
|
#subtask_sp = float(comment_line[right:])
|
||||||
|
assignee = get_assignee(type)
|
||||||
|
issue_dict = {
|
||||||
|
'project': {'id': 12501},
|
||||||
|
'summary': "[{}] {}".format(type, escaped),
|
||||||
|
'description': issue.fields.description,
|
||||||
|
'issuetype': {'name': 'Sub-task'},
|
||||||
|
'parent': {'key': parent},
|
||||||
|
# todo - json
|
||||||
|
#'components': [{'name': issue.fields.components}],
|
||||||
|
#'labels': [{'name': issue.fields.labels}],
|
||||||
|
'timetracking': {'originalEstimate': "{}d".format(subtask_sp)},
|
||||||
|
'assignee': {'name': assignee}
|
||||||
|
}
|
||||||
|
new_issue = jira_server.create_issue(fields=issue_dict)
|
||||||
|
|
||||||
|
# consider components
|
||||||
|
existingComponents = []
|
||||||
|
for component in issue.fields.components:
|
||||||
|
existingComponents.append({"name" : component.name})
|
||||||
|
new_issue.update(fields={"components": existingComponents})
|
||||||
|
|
||||||
|
logging.info('Created Sub-Task {}'.format(new_issue))
|
||||||
|
else:
|
||||||
|
logging.info('Skip creating Sub-Task {} for {} as it already exists'.format(type, issue))
|
||||||
|
|
||||||
|
logging.basicConfig(filename='sub_task_generator.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})
|
||||||
|
|
||||||
|
#issues_Jql = jira_server.search_issues('filter=19527') #, expand='changelog')
|
||||||
|
issues_Jql = jira_server.search_issues('labels in (Refinement11012022) AND type not in (Bug) AND status not in (Done) and ("Story Points" is EMPTY or "Story Points" = 0)') #, expand='changelog')
|
||||||
|
|
||||||
|
logging.info('Creating sub-tasks out of estimation of pre-planning sprint {}'.format(38))
|
||||||
|
xsp = lambda s: s or 0
|
||||||
|
|
||||||
|
issue: Issue
|
||||||
|
for issue in issues_Jql:
|
||||||
|
logging.info('Working on {}'.format(issue))
|
||||||
|
sp_sum = 0
|
||||||
|
|
||||||
|
# sp = 0
|
||||||
|
# if hasattr(issue.fields, 'customfield_10022'):
|
||||||
|
# sp = xsp(issue.fields.customfield_10022)
|
||||||
|
# sp_sum += sp
|
||||||
|
|
||||||
|
single_issue = jira_server.issue(issue.key)
|
||||||
|
comments = single_issue.fields.comment.comments
|
||||||
|
|
||||||
|
# Find all comments made by me on this issue.
|
||||||
|
for comment in comments:
|
||||||
|
comment_lines = comment.body.splitlines()
|
||||||
|
|
||||||
|
if len(comment_lines) == 5:
|
||||||
|
for comment_line in comment_lines:
|
||||||
|
if comment_line != "":
|
||||||
|
# pos = comment_lines[2].find('NN')
|
||||||
|
comment_line_parts = comment_line.split(':')
|
||||||
|
|
||||||
|
# if 1. Test* != NN create a sub-task (if not existing)
|
||||||
|
if len(comment_line_parts) == 2:
|
||||||
|
if comment_line_parts[1] != u'\xa0': # empty string
|
||||||
|
if comment_line_parts[1][-2:] != 'NN': # NN means NotNecessary
|
||||||
|
subtask_ph = float(comment_line_parts[1]) * 0.5
|
||||||
|
if comment_line_parts[0][:15] != "Test-Ausführung":
|
||||||
|
create_subtask(issue,
|
||||||
|
issue.key,
|
||||||
|
comment_line_parts[0],
|
||||||
|
subtask_ph)
|
||||||
|
sp_sum += subtask_ph / 0.5
|
||||||
|
|
||||||
|
# find corresponding sub-task
|
||||||
|
# issuelinks.inwardIssue
|
||||||
|
try:
|
||||||
|
issue.update(fields={'customfield_10022': sp_sum})
|
||||||
|
logging.info("Estimated story-points changed to Sum(Sub-Tasks story-points): {}".format(sp_sum, sp_sum))
|
||||||
|
|
||||||
|
except exceptions.JIRAError:
|
||||||
|
logging.error("Issue {} has no (visible) Story Points-attribute".format(issue.key))
|
||||||
|
|
||||||
|
finally:
|
||||||
|
logging.info('Done {}'.format(issue.key))
|
||||||
|
|
||||||
|
#print('{}: {}, SP: {}'.format(issue.key, issue.fields.summary, sp))
|
||||||
|
|
||||||
|
#print('Summe {}: {}'.format(assignee, sp_sum))
|
||||||
|
|
||||||
|
#print(issues_Jql)
|
||||||
|
# changelog = issues_Jql.
|
||||||
|
# count = 0
|
||||||
|
# for history in changelog.histories:
|
||||||
|
# for item in history.items:
|
||||||
|
# if item.field == 'status':
|
||||||
|
# if item.toString == "Reopened":
|
||||||
|
# count = count + 1
|
||||||
|
# print(count)
|
||||||
|
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
# recalculate historical estimations
|
||||||
|
# zisco 2021-10-05 15:54
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from types import ClassMethodDescriptorType
|
||||||
|
from jira import JIRA, Issue, Comment, exceptions
|
||||||
|
import re
|
||||||
|
import csv
|
||||||
|
import xlsxwriter
|
||||||
|
|
||||||
|
logging.basicConfig(filename='jahe.log', filemode='a', format='%(asctime)s - %(message)s', level=logging.INFO)
|
||||||
|
|
||||||
|
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")
|
||||||
|
|
||||||
|
# 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('key in (wrgwr-856, wrgwr-854, wrgwr-853)', 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 = issue.fields.timeoriginalestimate
|
||||||
|
logging.info("Estimation-system change: Old Story Points {} -> new Story Points {}".format(sp, sp/8))
|
||||||
|
|
||||||
|
# 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': sp/8})
|
||||||
|
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))
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
# suche alle issues, wo (original estimate * 2) != story points
|
||||||
|
# korrigiere story points auf original estimate * 2
|
||||||
|
|
||||||
|
# zisco 2021-10-05 15:54
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from types import ClassMethodDescriptorType
|
||||||
|
from jira import JIRA, Issue, Comment, exceptions
|
||||||
|
import re
|
||||||
|
import csv
|
||||||
|
import xlsxwriter
|
||||||
|
|
||||||
|
logging.basicConfig(filename='jahe.log', filemode='a', format='%(asctime)s - %(message)s', level=logging.INFO)
|
||||||
|
|
||||||
|
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")
|
||||||
|
|
||||||
|
# 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))
|
||||||
@@ -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)) """
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
[{
|
||||||
|
"Kratochvil Jakub": "JIRAUSER16603", "games": ["Spiderman","God of War"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"JIRAUSER17211": "Zimmerberger Markus"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Cervenka Raimund": "JIRAUSER14400"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Reischitz Ulf": "reu9001"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Kremser Peter": "krp9002"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Thüringer Helfried": "JIRAUSER15724"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Blagojevic Nikolina": "JIRAUSER17212"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Unfried Daniel": "und9001"
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
[{
|
||||||
|
"elsap": "Kratochvil Jakub",
|
||||||
|
"name": "krj0003",
|
||||||
|
"key": "JIRAUSER16603"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"elsap": "Zimmerberger Markus",
|
||||||
|
"name": "zim9003",
|
||||||
|
"key": "JIRAUSER17211"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"elsap": "Cervenka Raimund",
|
||||||
|
"name": "ce39001",
|
||||||
|
"key": "JIRAUSER14400"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"elsap": "Reischitz Ulf",
|
||||||
|
"name": "reu9001",
|
||||||
|
"key": "reu9001"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"elsap": "Kremser Peter",
|
||||||
|
"name": "krp9002",
|
||||||
|
"key": "krp9002"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"elsap": "Thüringer Helfried",
|
||||||
|
"name": "thh9001",
|
||||||
|
"key": "JIRAUSER15724"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"elsap": "Blagojevic Nikolina",
|
||||||
|
"name": "bln9001",
|
||||||
|
"key": "JIRAUSER17212"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"elsap": "Unfried Daniel",
|
||||||
|
"name": "und9001",
|
||||||
|
"key": "und9001"
|
||||||
|
}
|
||||||
|
]
|
||||||
Reference in New Issue
Block a user